Django-模板继承/组件/自定义标签
一、标签tags
for标签
遍历每一个元素: 写个for,然后 tab键自动生成for循环的结构,循环很基础,就这么简单的用,没有什么break之类的,复杂一些的功能,你要通过js
def get(self,request): lit = ["一","二","三"] return render(request,"login.html",{"lit":lit})
{% for foo in lit %} {{ forloop.counter}} {{ foo }} {% endfor %}
标签看起来像是这样的: {% tag %}
。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...
标签 内容 ... {% endtag %})。
注:循环序号可以通过{{forloop}}显示,必须在循环内部用
forloop.counter 当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
可以利用{% for obj in list reversed %}反向完成循环。
empty
for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
def get(self,request): lit = [] return render(request,"login.html",{"lit":lit})
{% for foo in lit reversed %} {{ forloop.counter}} {{ foo }} {% empty %} sorry {% endfor %}
if标签
{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
{% if num > 100 or num < 0 %} <p>无效</p> <!--不满足条件,不会生成这个标签--> {% elif num > 80 and num < 100 %} <p>优秀</p> {% else %} <!--也是在if标签结构里面的--> <p>凑活吧</p> {% endif %}
当然也可以只有if和else
{% if user_list|length > 5 %} <!--结合过滤器来使用--> 七座豪华SUV {% else %} 黄包车 {% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。
注意事项
1. Django的模板语言不支持连续判断,即不支持以下写法:
{% if a > b > c %} ... {% endif %}
2. Django的模板语言中属性的优先级大于方法(了解)
def xx(request): d = {"a": 1, "b": 2, "c": 3, "items": "100"} return render(request, "xx.html", {"data": d})
如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:
{{ data.items }}
默认会取d的items key的值。
二、csrf_token
我们以post方式提交表单的时候,会报错,还记得我们在settings里面的中间件配置里面把一个csrf的防御机制给注销了啊,本身不应该注销的,而是应该学会怎么使用它,并且不让自己的操作被forbiden,通过这个东西就能搞定。
这个标签用于跨站请求伪造保护,
在页面的form表单里面(注意是在form表单里面)任何位置写上{% csrf_token %},这个东西模板渲染的时候替换成了<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,隐藏的,这个标签的值是个随机字符串,提交的时候,这个东西也被提交了,首先这个东西是我们后端渲染的时候给页面加上的,那么当你通过我给你的form表单提交数据的时候,你带着这个内容我就认识你,不带着,我就禁止你,因为后台我们django也存着这个东西,和你这个值相同的一个值,可以做对应验证是不是我给你的token,存储这个值的东西我们后面再学,你先知道一下就行了,就像一个我们后台给这个用户的一个通行证,如果你用户没有按照我给你的这个正常的页面来post提交表单数据,或者说你没有先去请求我这个登陆页面,而是直接模拟请求来提交数据,那么我就能知道,你这个请求是非法的,反爬虫或者恶意攻击我的网站,以后将中间件的时候我们在细说这个东西,但是现在你要明白怎么回事,明白为什么django会加这一套防御。
<form action="/login/" method="post"> {% csrf_token %} # 在form表单的任意位置添加 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <button>登录</button> </form>
跨站请求伪造保护的几种应用:
1、全局配置(在settings配置)
这种配置表示给所有的post请求添加了csrf防御机制;
2、装饰器的两种形式
from django.views.decorators.csrf import csrf_exempt # 放行csrf认证,即便是全局配置了csrf认证 @csrf_exempt # post请求执行的函数 def post(self,request): user = request.POST.get("username") pwd=request.POST.get("password") if user=="chao" and pwd=="123": return render(request,"successfully.html") else: return HttpResponse("用户名密码错误")
from django.views.decorators.csrf import csrf_protect # 强制csrf认证,即便是全局没有配置csrf认证 @csrf_protect # post请求执行的函数 def post(self,request): user = request.POST.get("username") pwd=request.POST.get("password") if user=="chao" and pwd=="123": return render(request,"successfully.html") else: return HttpResponse("用户名密码错误")
三、模板继承
Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks
创建模板:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> {% block style %} .c1{ background-color: red; height: 200px; width: 200px; } {% endblock %} </style> </head> <body> <div class="c1"> {% block content %} <p>这是模板</p> {% endblock %} </div> </body> </html>
{% block content %} <p>这是模板</p> {% endblock %} 凡是被大括号包裹的内容表示,该模板被继承后这个内容可以自定义
继承模板:
<!--继承模板,必须写在最上面--> {% extends '模板.html' %} {% block style %} .c1{ background-color: yellow; height: 100px; width: 100px; } {% endblock style %} {% block content %} <!--保留模板内容--> {{ block.super }} <p>继承后重写样式</p> {% endblock content %}
根据名字指定到哪里结束,使用block.super可以保留模板内容
-
为了更好的可读性,你也可以给你的
{% endblock %}
标签一个 名字 。例如:
{% block content %} ... {% endblock content %}
在大型模版中,这个方法帮你清楚的看到哪一个 {% block %}
标签被关闭了。
- 不能在一个模版中定义多个相同名字的
block
标签。
四、组件
嵌入语法:
{% include 'navbar.html' %}
可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方,文件的任意位置按如下语法导入即可。
例如:有个如下的导航栏,nav.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .c1{ background-color: red; height: 40px; } </style> </head> <body> <div class="c1"> <div> <a href="">xx</a> <a href="">dd</a> </div> </div> </body> </html>
嵌入导航栏的页面,test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include 'nav.html' %} <h1>xxxxxxxxxx</h1> </body> </html>
组件和插件的简单区别:
组件是提供某一完整功能的模块,如:编辑器组件,QQ空间提供的关注组件 等。
而插件更倾向封闭某一功能方法的函数。
这两者的区别在 Javascript 里区别很小,组件这个名词用得不多,一般统称插件。
五、自定义标签和过滤器
自定义过滤器:
@register.filter
一、app01应用文件夹中创建一个叫做templatetags的文件夹;
例如:
二、创建视图函数并传参数
def tags(request): num=100 return render(request,"tags.html",{"num":num})
三、在templatetags文件夹里创建一个py文件用于创建过滤器;
from django import template # 生成模板注册器 register = template.Library() @register.filter def func(v1,v2): """ 过滤器参数 :param v1: 变量值 :param v2: 过滤器参数值 :return: """ return v1*v2
四、在前端页面导入过滤器并放变量等待接收参数
{% load mytag %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ num|func:10 }} </body> </html>
注意:{% load mytag %} 必须放在整个html的最上面
结论:也就是说num接收服务器传参数100,又经过我们自定义的过滤器进行了二次加功,最后将过滤器的返回值发送给了前端有{{返回值}}
过滤器的参数最多只能有两个:
想要传多个参数如下:
页面效果:
如果同时使用模板继承和自定义过滤器,引入顺序:
自定义标签:
1、2步同自定义过滤器:
@register.simple_tag()
为了放置XSS攻击所以在自定义标签中返回的标签在模板中渲染后还是文本
前端页面效果:
使用mark_safe()方法让其正常显示标签:
页面效果:
@register.inclusion_tag("文件名.html")