1. 介绍
- 模板配置在settings.py中:
DIRS中定义一个目录列表,模板引擎按列表顺序搜索这些目录来查找模板文件,通常在根目录下创建templates目录。模板包含两部分:
- 静态部分:html, css, js;
- 动态部分:模板语言;
- django处理模板分为两个阶段:
- 加载:按照指定目录找到模板文件,编译后加载至内存;
- 渲染:使用上下文数据对模板插值并返回生成的字符串;
- django提供简写模板render函数来调用模板。
- 模板语言包含4种类型:变量,标签, 过滤器, 注释。
2. 模板语言
2.1 模板变量
- 语法:
{{ 变量 }}
- 当模板引擎遇到
.
符号如book.title
时,会安如下顺序解析:
- 字典:
book['title']
;
- 对象属性/方法:先按
book.title
查找book对象的属性,再按book.title()
查找book对象的title方法;
- 如果格式是
book.0
则解析为列表book[0]
;- 如多都没有则对应处为空字符串。
- 注意:模板中调用方法时不能传递参数。
2.2 标签
- 语法:
{% 代码段 %}
- for标签:
{% for item in itemlist %}
逻辑
{% forloop.counter%} # 表示当前是第几次循环,从1开始
{% empty %}
列表为空或不存在时逻辑
{% endfor %}
- if标签
{% if ... %}
逻辑...
{% elif ... %}
逻辑...
{% else %}
逻辑...
{% endif %}
- 比较运算法
==, !=, >, <, >=, <=
注意:比较运算法两侧必须有空格,不能紧挨变量或常量。
- 布尔运算符
and, or, not
2.3 过滤器
- 语法:
变量 | 过滤器:参数 # 注意“:”前后不能有空格
- length:返回字符串字符数或者列表,元组或字典的元素个数;
- default:变量不存在时返回默认值;
- date:日期类型的值进行字符串格式化:
- Y:4位年,y表示2位年;
- m:月,格式为01,02...
- d:日,01, 02...
- j:日,1,2...
- H:24进制时
- h:12进制时
- i:分,0-59
- s:秒,0-59
2.4 自定义过滤器
- 在应用中创建templatetags目录(需包含__ init __.py文件);
- 在templatetags下创建filters.py文件:
- 使用模块:
在模板中导入过滤器即可在下面使用。
- 自定义过滤器可以增加参数:
传参仍是冒号相连。
2.5 注释
在模板中使用模板注释,代码不会被编译,不会输出到客户端,html只能注释html内容,不能注释模板语言。
- 单行语法注释:
{#...#}
-2. 多行注释:
{%comment%}
...
{%endcomment%}
3. 模板继承
父模版:
子模版:extends继承写在子模板文件第一行。
4. html转义
模板对上下文传递的字符串进行输出时,会对以下字符串进行自动转义:
>
转义为>
;<
转义为<
;'
转义为'
;"
转义为"
;&
转义为&
;- 关闭转义:
- 过滤器
safe
,示例:{{ data | safe}}
;
- 使用
autoescape
,示例:
{% autoescape off
%}
代码块...
{% endescape %}
模板硬编码不转义,如:{{ data | default:'<h1>hello world</h1>'}}
5. CSRF
CSRF:Cross Site Request Forgery,跨站请求伪造。
django防止csrf攻击:使用csrf中间件:
使用:1. settings.py中开启中间件;2. 在post的form表单中加入csrf_token标签:{% csrf_token %}
原理:当启用中间件并加入标签csrf_token后,会向客户端浏览器中写入一条Cookie信息,这条信息的值与隐藏域input元素的value属性是一致的,提交到服务器后会先由csrf中间件进行验证,如果对比失败则返回403页面,而不会进行后续的处理。
6. 验证码
验证码在网上很多,这里以一个案例为例
- 安装Pillow包
pip install Pillow==3.4.1
- 安装Pillow包
- 定义视图
from django.http import HttpResponse
from PIL import Image, ImageDraw, ImageFont
from django.utils.six import BytesIO
# Create your views here.
def verify_code(request):
# 引入随机函数模块
import random
# 定义变量,用于画面的背景色/宽/高
bgcolor = (random.randrange(20, 100), random.randrange(20, 100), 255)
width = 100
height = 25
# 创建画面对象
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 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
# 随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str1[random.randrange(0, len(str1))]
# 构造字体对象
font = ImageFont.truetype('/static/font/Tahoma.ttf', 23)
# 构造字体颜色
fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
# 绘制4个字
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')
效果:注意是在项目中拷贝一份字体文件:
如果字体没找到会报错:
-
- 简单使用
- 定义验证码页面:
- 定义视图:
- 页面效果
7. 反向解析
在之前的url配置时,无论模板中链接路径还是后台返回页面地址,都是严格按url中正则表达式来写的,这样存在的问题就是一旦url中正则表达式变了,所有已经完成的路径都得作相应改动。反向解析就是解决该问题的。反向解析用在两个地方:
- 模板中超链接
- 视图中重定向
- 反向解析使用:
先在项目urls.py包含应用url时,include中增加namespace参数:
url(r'^', include('booktest.urls', namespace='booktest'))
在应用中urls.py中配置路径时,增加name参数name参数:
url(r'^index$', views.index, name='index')
- 在模板超链接中使用:使用url标签:
<a href="{% url 'booktedt:index' %}">首页</a>
- 在重定向中使用:
a. 先导入reverse模块:
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
b. 在视图中重定向:
return redirect(reverse('booktest:index'))
- 反向解析结果:
在使用反向解析后,无论模版超链接还是重定向,都会自动根据正则表达式生成相应的链接完成跳转。
- 反向解析传参:
- 位置参数:
url配置:
url(r'^index/(\d+)/(\d+)$', views.index, name='index')
a. 超链接传参:
<a href="{% url 'booktest:index' 2 3 %}">首页</a>
# 自动解析为/booktest/index/2/3
b. 重定向传参:
return redirect(reverse('booktest:index', args=(2, 3)))
- 关键字参数:
url配置:
url(r'^index/(?P<id>\d+)/(?P<age>\d+)$', views.index, name='index')
a. 超链接传参:
<a href="{% url 'booktest:index' id=2 age=10 %}">首页</a>
b. 重定向传参:
return redirect(reverse('booktest:index', kwargs={'id':2,'age':10}))