模板T功能
生成html,包括静态内容和动态内容,静态css,js,html
动态,用模板语言生成
视频里因为是使用pycharm专业版,而我使用的是社区版,尴尬,还得重头配置个项目test2,应用用booktest,其他都可以在第一章里看到,我们把项目的settings里databases,时区,语言还有模板文件都配置好,还有urls配置到booktest的urls访问
这回,在模板文件夹templates下面创建booktest文件夹,创建页面index.html
模板文件的使用
我们a加载模板文件,这个是django内部给我们处理,b定义上下文,给模板传送数据,让模板可以使用数据,c
渲染页面,通过数据替换对应值,生成最终html页面
我们在views.py里定义视图函数index,如上,同时配置urls
模板文件的加载顺序
上图是我们定义尝试访问index2页面,因为还有没有定义,我们可以看到模板文件在booktest下没有找到,而且他还会从2个已经注册的应用admin和auth里去找,也没有找到
他会在我们配置的DIRS列表去寻找,如果没有,就在INSTALLED_APPS里面寻找,前提是里面有templates文件夹
模板标签传参
我们模板页面里支持代码段和变量,上图是我们之前讲的books取元素用ul显示,用{%%}结构,记得循环结束用endfor也用{%%}包围,如果就是值,使用{{}}包裹
这个参数传递是通过视图函数的渲染传递的参数来实现
在循环中,我们还可以通过{{forloop.counter}} 得到for循环遍历了第几次,
当然我们还可以if 条件,elif 条件,else判断,结束用endif ,这些都用{%%}包裹
条件可以使用关系比较符>大于,<小于,>=大于等于,<=小于等于,!=不等于
注意关系比较时两边必须有空格
逻辑运算可以用not and or
我们可以给模板里设置判断id小于等于2的设置红色,elif id<=5设置黄色,剩下绿色,如图,好好分析代码
最后就实现了如上效果,还有很多相关的模板标签操作符,我们可以去查文档(好多,而且不是中文- -)
模板过滤器
过滤器和上面的函数一样也有很多,重点还是去理解函数,我们这里最先需要明白的就是格式: 模板变量|过滤器:参数,通过过滤器函数,实现模板变量的变化,我们可以给过滤器传入参数
如date,我们按照date格式化,可以提取Y,m,d年月日,让日期结果为中文,这个date可查出很多格式化的相关字母,可以去看文档
length不用参数,就是获得长度,这里相当于获取字符串长度,其实列表也可以
default对于之前的值如果为false就变成参数的默认值,我们可以设置个不存在的变量,这样上图就会显示内容
模板自定义过滤器
我们有的过滤器不能满足要求,需要我们自定义才能实现
我们需要在我们党的应用文件夹下创建templatetags包(名字不能错!!!,而且是package不是directory!!!)
我们可以在下面写过滤器py文件,比如我们起名filters.py(这个倒是可以自己起)
在filters.py里,我们需要先导入类from django.template import Library
然后创建一个类实例对象,我们使用实例对象的filter方法给我们定义的函数做装饰器
然后我们需要在html页面开头加载我们的过滤器,{%load filters%}这个filters是我们py文件名字,你换了也得和py文件一致
比如我们实现book.id的奇偶数判断就可以使用book.id|mod这里mod是我们定义的函数,而book.id这里自动作为num传入给函数,就可以实现奇偶数不同
我们什么时候用上:参数呢,如果我们的函数有2个参数,默认把第一个给|前的模板变量,:后的就是第二个参数,比如上图定义函数判断前者能否被后者整除
这样我们使用就可以这么写了。
注意我们自定义的函数,至少1个参数,最多2个参数!!!
模板注释
用{##}包含单行内容
多行注释{% comment %} 注释内容 {% endcomment%}
我们使用模板注释,审查元素是看不见的,但html自身注释是可见的<!--注释内容-->
模板继承
我们写模板,很多页面其实有共同属性,比如将很多模板都有导航条和最下面有版权信息
我们就可以基于此建立一个基础模板base.html,然后其他页面可以继承他比如child1,child2继承的页面自带导航条和版权信息,剩下多出来的地方额外设计就好
比如我们在模板文件夹创建base.html,里面写2个h1作为其自带的属性
我们可以另建child.html,然后我们不用写一大堆,导入base就可以实现父类页面内容,我们使用{% extends 'booktest/base.html' %}这里是从项目起的相对路径
写完页面,我们可以在视图里创建函数并配置urls,我们显示对应页面,可以看到child的页面和base的一样,注意,我们不能再child里面乱写其他东西,如果child里有和base不一样的地方,就需要父模板预留块
具体做法如上,我们{%block 快名%} 开始 {%endblock 快名%}结束,中间写内容,也可以不写,然后child里再次{%block 快名%} 开始 {%endblock 快名%}结束,中间写他自身的内容即可
我们修改base.html内容如上,如果我们不重新子模板,那child和base一样,
我们重写子模板的内容,就可以得到不同的效果
如果我们子模板还想要父模板的内容,我们可以添加{{block.super}}调用,这样之前父模板base的内容也会显示
当然我们还可设置多个块,每个块设置不同的块名,然后都要跟endblock 块名
最后我们总结下,如果模板相同尽可能的将内容整合到一起,不同的地方就可设置块
HTML转义
转义是什么呢,我们如果试图通过参数渲染页面,有些字符可能会被转义,导致没有出现我们的预期效果
我们配置函数,传给content的内容是个字符串,看着样子像h1标签,配置好urls,html里是通过{{content}}接收,
我们发现结果并不是h1标签,而是把模板变量内容原样显示出来
查看源代码,可以看到里面的符号并不是尖括号,而是被转义掉
在html里如果想显示如上变量,需要用专门的转义符号,我们使用渲染参数传递就是默认执行想被转义的效果,如果想关闭上下文转义,可以使用{{模板变量|safe}}或者
{%autoescape off%}模板变量代码段{%endautoescape%}
前者是单个模板变量取消转义,后者是批量模板变量取消转义
我们看下如上的几个代码,content第一个会被转义,|safe是单个不转义变成标签。autoescape包围2个content也会不转义,对于模板硬编码字符串不会转义,如倒数第二个,会被识别为h1标签,若我们想将其转义,就需要手动写转移码
效果如上
CSRF伪造(跨站请求伪造)
之前我们都是本机,这次我们使用inet地址,
我们在windows页面,就可以使用浏览器访问
我们设置change_pwd点击确认修改
点击以后就会访问change_pwd_action页面(这都是我们配置的,没配置就自己编个页面)
我们windows本机还有个index.html页面,有个按钮,是电脑上另外一个网站和项目没关系,我们点击以后,发现会切换到修改密码页面,而且密码被修改成了789,如下
这个问题就是我们说的csrf伪造的问题,我们登录后,浏览器和服务器沟通存储sessionid,我们再访问修改密码时,点击确认修改,返回修改页面,然后我们过程中没有退出项目页面,打开了第三方网站,同时点击了按钮
我们审查元素,就会看见index这个第三方网站干的‘不可见人的事情’,他将按钮绑定post方法,给我们默认提交了密码,这个input设置为隐藏的,我们也看不见,就会按将第三方网站给你设置的密码提交到修改密码页面,
这个csrf的作用点能成功的原因是:1我们浏览器访问正常网站,保留了sessionid,且没有退出
2我们同时打开了第三方网站,并可能进行了操作
其实django本身给我们提供了一个防止跨站请求的方式
MIDDLEWARE_CLASSES的第三行,是默认开启跨站请求防护的,之前被我们注释掉了,这个现在要取消注释
于是我们现在通过index点击按钮,会发现出现403错误,csrf防护,但是我们正常访问如上网站,也出现了403错误,这是因这django的csrf防护只针对post提交
为了不出现403,我们需要在几个表单提交的地方加上{%csrf_token%},上图是给login页面加
这里是给change_pwd_action页面加{%csrf_token%}
如上设置后,我们的正常登陆修改密码就没有问题了,但是通过第三方index.html就403错误
其实现原理,打开了csrf中间件,(即我们最开始要把settings.py那一项不要注释!!),表单post时,加上{%csrf_token%}
防御原理,渲染时,给页面生成一个csrfmiddlewaretoken的隐藏域,同时,给浏览器响应里有csrftoken的cookie信息,提交表单时,会将2个值进行比对,一样则通过,否则失败
可以看到隐藏域
我们可以看到点击登录,有cookie里的csrftoken,值和隐藏域一样,提交后进行2个值的判断,一样即ok,否则失败,我们index页面没有这个隐藏域(csrftoken会发过去),所以会失败
(当然有人说第三方网站把隐藏域贴过去就能访问了,的确是这样,但是现实中,第三方往往并不知道我们的隐藏域的位置,当然如果泄密另说,只能说csrf也是有限的)
最后为了项目安全,所有表单post提交都加上{%csrf_token%},而且记得settings.py那里不要注释!!!
我们对于用户访问网页,可以用如上登录装饰器,限定用户登录才能获得页面
验证码
使用验证码,我们需要安装pillow库,视频版本是3.4.1,思路随机生成验证码字符串存于session中,然后通过生成图片,后展示给用户,用户输入后进行验证,和session中的进行比对,一致进行登录,否则重定向输入登录
我们在视图函数里导入,Image,ImageDraw,ImageFont为pillow内置类,我们还要导入django.utils.six 里的ByteIO类
在函数里,因为要随机,先生成随机背景色,设置尺寸,我们就可以创建一个im画布对象,然后我们创建画笔对象,用画笔把im画上去
然后我们在画笔上画100个噪点(作为干扰爬虫),随机位置,颜色。我们备选验证码文字使用str1字符串存储,然后用rand_str获得随机4位验证码,
然后我们创建字体对象,获得随机字体颜色,给每个字体画倒画笔上,然后删除画笔对象,情况
然后我们创建一个内存对象(我们没必要给每个图片都存到服务器),然后我们调用im存储图片到内存,并通过HttpResponse返回buf的值,使用getvalue(),这里需要加上'image/png'告诉浏览器是个png图片,
视图函数定义完,我们给其配置urls,重新启动服务
就可以看见页面显示验证码图片
这样我们就能给login页面加上img标签,里面的资源写我们刚配置的资源就行,这样我们访问login就获得了图片展示
我们为了让用户输入验证码,还要加上一个Input,指定name为vcode
我们然后就可以给login_check加上功能,我们通过vcode1获得表单POST提交的vcode内容,同时将session中存的verifycode获取,2个对比,如果不等,直接让其重定向到login,于是就可实现功能
反向解析
我们先创建一个反向解析的页面,里面一个超链接a,指向/index首页
我们写上视图函数,并带上urls配置
这样我们就能实现简单的链接到首页的超链接点击,假设有一天首页的地址变了,变成了index3,我们之前有很多直接指向'/index'的就都需要修改,而且容易出错,这就需要用到url反向解析
url反向解析的作用就是根据我们的urls配置,帮我们动态的解析资源,我们的链接等就没必要写死
如何反向解析设置
首先给项目的配置命名空间,我们之前include只有一个参数,现在我们加上关键字参数,namespace='booktest',一般使用应用名,
然后我们在urls里进行配置,也加上参数,name='index',这样我们的首页输入已经变成了index3
我们如上,对href属性用{%url 'booktest:index'%}这样,里面的booktest即我们的命名空间,index即我们刚才urls配置name,
我们访问url_reverse页面,可以看到我们用反向解析的部分已经动态换到我们的index3,这样即使页面的配置资源urls改了,我们也不需要改html内容
又比如我们想给视图函数传参数,如上用正则传入,同时给命名
我们加上urls参数,并视图加上函数,我们这里就简单的显示a:b
我们页面如下
我们写一个href写死的,就是/show_args/1/2,然后我们写一个动态解析的,
还是里面{%url 'booktest:show_args' 1 2%}因为我们函数要2个参数,所以这里加上空格1空格2
访问同样可以看到动态生成的效果
当然我们urls配置里有时候也会用关键字参数,如下图,子组命名c,d,同时第三个参数加上命名name
我们视图函数里写函数,因为关键字是c,d所以,参数必须使用c,d,我们还是返回到页面显示c:d
我们就继续在页面写一个写死的参数,另一个是传关键字的参数,如下图,其中和无关键字参数的区别是,我们要写上c=3空格d=4,参数之间用空格隔开,同时参数名和值用=连接
当然我们右键查看源代码还是一样的效果
反向解析重定向怎么使用呢
比如上图我们要实现重定向首页,我们需要导入reverse解析函数,
from django.core.urlresolvers import reverse
reverse函数返回的是我们解析的网址,我们传入还是使用'命名空间:资源name'
然后返回这个重定向即可
上图又给我们写了如果想重定向到带参数或者关键字参数的解析,对于带参数我们除了传入'命名空间:资源name'传入第二个参数args=(参数构成的元组),对于关键字的,我们传入kwargs={关键字键值对字典}
我们项目中经常使用反向解析动态生成,防止一旦配置修改,我们要一动全身