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 ). 但是不允许在同一个 ...
随机推荐
- .NET Core中Circuit Breaker
谈谈Circuit Breaker在.NET Core中的简单应用 前言 由于微服务的盛行,不少公司都将原来细粒度比较大的服务拆分成多个小的服务,让每个小服务做好自己的事即可. 经过拆分之后,就避免不 ...
- BNU 4096 逆序 思维题
https://www.bnuoj.com/v3/problem_show.php?pid=4096 对于一个序列a,我们定义它的逆序数为满足a[i]>a[j]且i<j的有序对<i, ...
- MDX属性查询
SELECT NON EMPTY { { { { { AddCalculatedMembers([会员.会员ID].[会员ID].Members), [会员.会员ID].[(All)] } } } } ...
- jdk动态代理和cglib动态代理的区别
一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...
- sublime text 快捷键新建.vue
第一步:添加模板: 模板写法如下: <template> </template> <script type="ecmascript-6"> &l ...
- ES6学习(1)
let 和 const 命令 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效.for循环的计数器,就很合适使用let命令. 下面的代码 ...
- centos 安装 rtmp nginx 视频流服务器
---恢复内容开始--- 1.使用yum安装git yum -y install git 2.下载nginx-rtmp-module,官方github地址 // 通过git clone 的方式下载到服 ...
- 单列表变量与字符串拆分的对照(SqlServer)
最近遇到一个问题,在SQLServer中,需要根据用户传入的一系列ID值更新对应的记录.有两种方法,一种是将这些ID值使用逗号分隔,拼接成字符串传入,一种是以表变量的方式传入.最开始,我想当然的认为传 ...
- FlowVisor相关
1. FlowVisor工作原理(转) 作为一个网络虚拟化平台,FlowVisor部署在标准OpenFlow控制器和OpenFlow交换机之间,成为二者的透明代理.FlowVisor能够与多个控制器连 ...
- 关于一些Spring MVC控制器的参数注解总结
昨天同事问我控制器参数的注解的问题,我好久没那样写过,把参数和url一起设置,不过,今天我看了一些文章,查了一些资料,我尽可能的用我自己的理解方式来解释它吧! 1.@RequestParam绑定单个请 ...









