04 Django模板
- 基本概念
- 作为Web框架,Django提供了模板,用于编写html代码,还可以嵌入模板代码更快更方便的完成页面开发,再通过在视图中渲染模板,将生成最终的html字符串返回给客户端浏览器
- 模版致力于表达外观,而不是程序逻辑。模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用
- 组成
- 静态部分,包含html、css、js
- 动态部分,就是模板语言
- 模板文件
- 模板文件的加载顺序
- 首先去配置的模板目录下面去找模板文件
- 去INSTALLED_APPS下面的每个应用的templates去找模板文件,前提是应用中必须有templates文件夹
- 模板语言
- 模板语言简称为 DTL(Django Template Language)
- 模板变量
- 模板变量名是由数字,字母,下划线和点组成的,不能以下划线开头
- 使用模板变量
{{模板变量名}} |
- 模板变量的解析
- 解析顺序
- {{ book.btitle }}
- 首先把 book 当成一个字典,把 btitle 当成键名,进行取值 book['btitle']
- 把 book 当成一个对象,把 btitle 当成属性,进行取值 book.btitle
- 把 book 当成一个对象,把 btitle 当成对象的方法,进行取值 book.btitle
- {{ book.0 }}
- 首先把book当成一个字典,把0当成键名,进行取值book[0]
- 把book当成一个列表,把0当成下标,进行取值book[0]
- 如果解析失败,则产生内容时用空字符串填充模板变量。
- 使用模板变量时,. 前面的可能是一个字典,可能是一个对象,还可能是一个列表
- 模板标签
- 使用方法
{% 代码段 %} |
- for 循环
{% for x in 列表 %} # 列表不为空时执行 {% empty %} # 列表为空时执行 {% endfor %} |
- 可以通过 {{ forloop.counter }} 得到 for 循环遍历到了第几次
- 条件语句
{% if 条件 %} {% elif 条件 %} {% else %} {% endif %} |
- 关系比较运算符
- > < >= <= == !=
- 进行比较运算时,比较操作符两边必须有空格
- 逻辑运算
- not and or
模板变量|过滤器:参数 |
- 其中 : 后不能有空格
- 常用过滤器
- date
- 改变日期的显示格式
- length
- 求长度。字符串,列表.
- default
- 设置模板变量的默认值
- 自定义过滤器
- 至少有一个参数,最多只能有两个参数
- 示例:一个参数
- 在应用中创建templatetags目录,当前示例为"booktest/templatetags"(文件名不可更改),创建__init__文件,内容为空
- 在"booktest/templatetags"目录下创建 filters.py (文件名可自定义)文件,代码如下:
#导入Library类 from django.template import Library #创建一个Library类对象 register=Library() #使用装饰器进行注册 @register.filter 求余 def iseven(value): |
- 在 templates/booktest/temp_filter.html 中,使用自定义过滤器
- 首先使用load标签引入模块
{%load filters%} |
- 在遍历时根据编号判断奇偶,调用格式如下
显示 id 为偶数的图书 <ul> {% for book in books %} {% if book.id|iseven %} <li class="red">{{ book.id }}--{{book.btitle}}-- {{ book.bpub_date|date:"Y 年 m 月 d 日" }}</li> {% endif %} {% endfor %} </ul> |
- 示例:两个参数,其中接收一个参数
- 在 filters.py 中添加如下函数
@register.filter def mod(num, dividend): """判断 num 是否能被 dividend 整除""" |
- 在使用load标签引入模块后,调用格式如下:
显示 id 能被 3 整除的图书 <ul> {% for book in books %} {% if book.id|mod:3 %} <li class="red">{{ book.id }}--{{book.btitle}}-- {{ book.bpub_date|date:"Y 年 m 月 d 日" }}</li> {% endif %} {% endfor %} </ul> |
- 模板注释
- 单行注释
{# 注释内容 #} |
- 多行注释
{% comment %} 注释内容 {% endcomment %} |
- 模板继承
- 示意图
- 在父模板中可以定义块
{% block 块名 %} 块中间可以写内容,也可以不写 {% endblock 块名%} |
- 子模板的继承格式
{% extends 父模板文件路径%} |
- 子模块对块中的内容进行操作
{% block 块名 %} {{ block.super}} #获取父模板中块的默认内容 重写的内容 {% endblock 块名%} |
- html 转义
- 在模板上下文中的 html 标记默认是会被转义的
- 小于号< 转换为<
- 大于号> 转换为>
- 单引号' 转换为'
- 双引号" 转换为 "
- 与符号& 转换为 &
- 关闭上下文字符串的方法
{{ 模板变量|safe}} |
- 使用 autoesacpe 标签
{% autoescape off %} 模板语言代码 {% endautoescape %} |
- 模板硬编码中的字符串默认不会经过转义
模板硬编码不转义:{{data|default:'<b>hello</b>'}} <br /> 模板硬编码手动转义:{{data|default:"<b>123</b>"}} |
- csrf 攻击
- 基本概念
- CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造
- 指攻击者盗用了你的身份,以你的名义发送恶意请求
- CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......
- 造成的问题包括:个人隐私泄露以及财产安全
- 示意图
- 防止方法
- 首先是重要的信息传递都采用 POST 方式而不是 GET 方式
- POST 方式避免 csrf 攻击需要采取特殊的措施
- django 中的防止方法
- 在 setting.py 中启用 csrf 中间件
- 在 form 表单中使用标签 csrf_token
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>发帖页</title> </head> <body> <form method="post" action="/post_action/"> {% csrf_token %} 标题:<input type="text" name="title"/><br/> 内容:<textarea name="content"></textarea> <input type="submit" value="发帖"/> </form> </body> </html> |
- django 中的保护原理
- 加入标签后,可以查看网页的源代码,会发现多了一个隐藏域
- 查看 cookie 信息
- 当启用中间件并加入标签csrf_token后,会向客户端浏览器中写入一条 Cookie 信息,这条信息的值与隐藏域 input 元素的 value 属性是一致的,提交到服务器后会先由 csrf 中间件进行验证,如果对比失败则返回 403 页面,而不会进行后续的处理
- 验证码
- 在用户注册、登录页面,为了防止暴力请求,可以加入验证码功能,如果验证码错误,则不需要继续处理,可以减轻业务服务器、数据库服务器的压力
- 实现验证码
- 在当前环境中安装包 Pillow 3.4.1
- PIL模块API,示例中使用了 Image、ImageDraw、ImageFont对象及方法
- 在booktest/views.py文件中,创建视图verify_code
- 随机生成字符串后存入session中,用于后续判断
- 视图返回 mime-type 为image/png
from PIL import Image, ImageDraw, ImageFont from django.utils.six import BytesIO ... def verify_code(request): #引入随机函数模块 import random #定义变量,用于画面的背景色、宽、高 bgcolor = (random.randrange(20, 100), random.randrange( 20, 100), 255) #创建画面对象 im = Image.new('RGB', (width, height), bgcolor) #创建画笔对象 draw = ImageDraw.Draw(im) #调用画笔的point()函数绘制噪点 for i in range(0, 100): xy = (random.randrange(0, width), random.randrange(0, height)) fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) draw.point(xy, fill=fill) #定义验证码的备选值 str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0' 个值作为验证码 rand_str = '' for i in range(0, 4): rand_str += str1[random.randrange(0, len(str1))] #构造字体对象,ubuntu的字体路径为"/usr/share/fonts/truetype/freefont" font = ImageFont.truetype('FreeMono.ttf', 23) #构造字体颜色 fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255)) 个字 draw.text((5, 2), rand_str[0], font=font, fill=fontcolor) draw.text((25, 2), rand_str[1], font=font, fill=fontcolor) draw.text((50, 2), rand_str[2], font=font, fill=fontcolor) draw.text((75, 2), rand_str[3], font=font, fill=fontcolor) #释放画笔 del draw #存入session,用于做进一步验证 request.session['verifycode'] = rand_str #内存文件操作 buf = BytesIO() #将图片保存在内存中,文件类型为png im.save(buf, 'png') #将内存中的图片数据返回给客户端,MIME类型为图片png return HttpResponse(buf.getvalue(), 'image/png') |
- 打开 booktest/urls.py 文件,配置 url
url(r'^verify_code/$', views.verify_code), |
- 浏览器效果图
- 刷新后验证码会发生变化
- 调用验证码
- 在booktest/views.py文件中,创建视图verify_show
def verify_show(request): return render(request,'booktest/verify_show.html') |
- 打开booktest/urls.py文件,配置url
url(r'^verify_show/$', views.verify_show), |
- 在templates/booktest/目录下创建verify_show.html
<html> <head> <title>验证码</title> </head> <body> <form method="post" action="/verify_yz/"> {%csrf_token%} <input type="text" name="yzm"> <img id="yzm" src="/verify_code/"> <span id="change">看不清,换一个</span> <br> <input type="submit" value="提交"> </form> </body> </html> |
- 浏览效果
- 验证
- 在 booktest/views.py 文件中,创建视图 verify_yz
def verify_yz(request): yzm=request.POST.get('yzm') verifycode=request.session['verifycode'] response=HttpResponse('no') if yzm==verifycode: response=HttpResponse('ok') return response |
- 打开booktest/urls.py文件,配置url
url(r'^verify_yz/$', views.verify_yz), |
- 浏览器中的效果
- url 反向解析
- 当某一个url配置的地址发生变化时,页面上使用反向解析生成地址的位置不需要发生变化
- 反向解析应用在两个地方:模板中的超链接,视图中的重定向
- 要实现反向解析功能,需要如下步骤:
- 在 test4/urls.py中 为 include 定义 namespace 属性
url(r'^',include('booktest.urls',namespace='booktest')), |
- 在booktest/urls.py中为url定义name属性,并修改为fan2
url(r'^fan2/$', views.fan2,name='fan2'), |
- django 2.0 版本需要指定 app_name
app_name = 'cart' |
- 在模板中使用url标签做超链接,此处为 templates/booktest/fan1.html 文件
<html> <head> <title>反向解析</title> </head> <body> 普通链接:<a href="/fan2/">fan2</a> <br> 反向解析:<a href="{%url 'booktest:fan2'%}">fan2</a> </body> </html> |
- 浏览器中查看源代码
- 在 booktest/urls.py 中,将 fan2 修改为 fan_show
url(r'^fan_show/$', views.fan2,name='fan2'), |
- 回到浏览器中,刷新,查看源文件如下图,可看出两个链接地址不一样
- 应用于视图重定向中
from django.shortcuts import redirect from django.core.urlresolvers import reverse return redirect(reverse('booktest:fan2')) |
- 相关总结
- 在模板中
- 无参数
{% url 'namespace名字:name' %} 例如{% url 'booktest:fan2'%} |
- 位置参数
{% url 'namespace名字:name' 参数 %} 例如{% url 'booktest:fan2' 1 2%} |
- 关键字参数
{% url 'namespace名字:name' 关键字参数 %} 例如{% url 'booktest:fan2' id=1 name='lijunjie'%} |
- 在视图重定向中
- 首先导入 reverse 模块
from django.core.urlresolvers import reverse |
- 无参数
reverse('namespace名字:name名字') |
- 位置参数
reverse('namespace名字:name名字', args = 位置参数元组) |
- 关键字参数
reverse('namespace名字:name名字', kwargs=字典) |
04 Django模板的更多相关文章
- Ubuntu14.04 Django Mysql安装部署全过程
Ubuntu14.04 Django Mysql安装部署全过程 一.简要步骤.(阿里云Ubuntu14.04) Python安装 Django Mysql的安装与配置 记录一下我的部署过程,也方便 ...
- Django模板与Vue.js冲突问题
参考: https://my.oschina.net/soarwilldo/blog/755984 方法1:修改vue.js的默认的绑定符号 Vue.config.delimiters = [&quo ...
- 在 Django 模板中遍历复杂数据结构的关键是句点字符
在 Django 模板中遍历复杂数据结构的关键是句点字符 ( . ). 实例二 mysit/templates/myhtml2.html修改如下 <!DOCTYPE html> <h ...
- python django 模板
1 用两个大括号括起来的文字{{person_name}} 称为变量 2 被 大括号和面分号包围的文件({% if ordered_warranty %})是模板标签 3 过滤器是用管道符(|) 和U ...
- django 模板中定义临时列表
<ul class="num_t clr"> {% for obj in ""|ljust:"10" %} <li> ...
- Django 模板中引用静态资源(js,css等)
Django 模板中免不了要用到一些js和CSS文件,查了很多网页,被弄得略晕乎,还是官网靠谱,给个链接大家可以自己看英文的. https://docs.djangoproject.com/en/1. ...
- Django模板-分离的模板
上一篇Django模板-在视图中使用模板最后的问题,我们需要把数据和展现分离开. 你可能首先考虑把模板保存在文件系统的某个位置并用 Python 内建的文件操作函数来读取文件内容. 假设文件保存在 E ...
- Django模板-在视图中使用模板
之前我们已经有了自己的视图mysite.views.py中,应该是这样子的 from django.http import HttpResponse import datetime def curre ...
- Django模板-模板标签
接着Django模板-基础知识继续写模板相关知识. if标签 {% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not ). 但是不允许在同一个 ...
随机推荐
- 洛谷 P3676 小清新数据结构题
https://www.luogu.org/problemnew/show/P3676 这题被我当成动态dp去做了,码了4k,搞了一个换根的动态dp #include<cstdio> #i ...
- 矩形面积并-扫描线 线段树 离散化 模板-poj1151 hdu1542
今天刚看到这个模板我是懵逼的,这个线段树既没有建树,也没有查询,只有一个update,而且区间成段更新也没有lazy标记....研究了一下午,我突然我发现我以前根本不懂扫描线,之所以没有lazy标记, ...
- dot watch
dot watch+vs code提升asp.net core开发效率 在园子中,已经又前辈介绍过dotnet watch的用法,但是是基于asp.net core 1.0的较老版本来讲解的,在asp ...
- setState异步函数
changeLeader(value){ console.log(value) this.setState({ leader:value },() => { console.lo ...
- NHibernate中创建User类报错问题
前两天刚开始学习NHibernate架构,照着前辈的例子打了一遍运行之后没问题,然后自己创建了一个User的Model发现一运行就报User附近有错误,然后就检查,类写的没错用了virtual,Use ...
- MoinMoin install in apache (win)
一:下载环境 xampp:http://sourceforge.net/projects/xampp/files/XAMPP%20Windows/1.8.1/xampp-win32-1.8.1-VC9 ...
- 13.JAVA-包package、import使用
1.包的定义 之前我们学习java时,生成的class文件都是位于当前目录中,假如出现了同名文件,则会出现文件覆盖问题,因此就需要设置不同的目录(定义包),来解决同名文件冲突问题. 并且在大型项目中, ...
- 51nod 1631 小鲨鱼在51nod小学
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 鲨鱼巨巨2.0(以下简称小鲨鱼)以优异的成绩考入了51nod小学.并依靠算法方面的特长,在班里担任了许多职务. ...
- Python学习——1113
在命令界面直接输入python,进入交互模式,相当于启动了Python解释器,需要一行一行的输入,输入一行,执行一行. 在命令界面直接运行.py文件,相当于直接启动了Python解释器,一次性把.py ...
- 【UML】对象图Object diagram(转)
http://blog.csdn.net/sds15732622190/article/details/48894751 前言 今天要说的是UML中的对象图.他与类图,合作图都有关系,是类图的实例化. ...