模板渲染的官方文档css
关于模板渲染你只须要记两种特殊符号(语法):html
在Django的模板语言中按此语法使用:{{ 变量名 }}。前端
当模版引擎遇到一个变量,它将计算这个变量,而后用结果替换掉它自己。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。python
深度查询据点符(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:数据库
字典查询(Dictionary lookup)
属性或方法查询(Attribute or method lookup)
数字索引查询(Numeric index lookup)django
注意事项:bootstrap
几个例子:后端
view中代码:浏览器
from django.shortcuts import render # Create your views here. def index(request): num = 100 name = 'anwen' lst = ['安文', 'didi'] # lst=[] dic = {'name': '安文', 'age': 23, 'hobby': '游泳'} class Animal(): def __init__(self): self.kind = 'dog' def eat(self): return 'chi' a = Animal() # xx='ll' filesize = '432511234.234' words = 'hello word i have a dream' tag = '<a href="http://www.baidu.com">百度</a>' import datetime time = datetime.datetime.now() # return render(request,'index.html',{'num':num,'name':name,'lst':lst,'dic':dic}) print(locals()) return render(request, 'index.html', locals())
模板index中支持的写法:缓存
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>数字:{{ num }}</p> <p>字符串:{{ name }}</p> <p>列表:{{ lst }}</p> <p>{{ lst.2 }}</p> <p>字典:{{ dic }}</p> <p>{{ dic.name }}</p> <p>类方法:{{ a.eat }}</p> </body> </html>
在Django的模板语言中,经过使用 过滤器 来改变变量的显示。
过滤器的语法: {{ value|filter_name:参数 }}
使用管道符"|"来应用过滤器。
例如:{{ name|lower }}会将name变量应用lower过滤器以后再显示它的值。lower在这里的做用是将文本全都变成小写。
注意事项:
Django的模板语言中提供了大约六十个内置过滤器。
若是一个变量是false或者为空,使用给定的默认值。 不然,使用变量的值。
<p>{{ xx|default:'啥都没有' }}</p> #若是value没有传值或者值为空的话就显示啥都没有
返回值的长度,做用于字符串和列表。
{{ value|length }}
返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
{#获取数据长度#} <p>{{ lst|length }}</p>
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。例如:
filesize = '432511234.234' <p>{{ filesize|filesizeformat }}</p> #若是filesize是432511234.234,输出将会是412.5 MB
切片,若是 value="hello world",还有其余可切片的数据类型
{#切片,若是 value="hello world",还有其余可切片的数据类型#} <p>{{ words|slice:'6:10' }}</p>
格式化,若是 value=datetime.datetime.now()
{{ value|date:"Y-m-d H:i:s"}} 关于时间日期的可用的参数(除了Y,m,d等等)还有不少,有兴趣的能够去查查看看。
若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:截断的字符数
words = 'hello word i have a dream' {{ words|truncatechars:9}} #注意:最后那三个省略号也是9个字符里面的,也就是这个9截断出来的是6个字符+3个省略号,有人会说,怎么展开啊,配合前端的点击事件就行啦
在必定数量的字后截断字符串,是截多少个单词。
例如:‘hello word i have a dream’,
{{ value|truncatewords:3}} #上面例子获得的结果是 'hello word i...'
移除value中全部的与给出的变量相同的字符串
hello word i have a dream {{ value|cut:' ' }} #hellowordihaveadream
使用字符串链接列表,{{ list|join:', ' }},就像Python的str.join(list)
lst = ['安文', 'didi','yage'] <p>{{ lst|join:'+' }}</p> #安文+didi+yage
标签看起来像是这样的: {% tag %}
。标签比变量更加复杂:一些在输出中建立文本,一些经过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签须要开始和结束标签 (例如{% tag %} ...
标签 内容 ... {% endtag %})。
遍历每个元素: 写个for,而后 tab键自动生成for循环的结构,循环很基础,就这么简单的用,没有什么break之类的,复杂一些的功能,你要经过js
{% for l in lst %} <p>{{ forloop.counter }}{{ l }}</p> <!--凡是变量都要用两个大括号括起来--> <!--for ... empty--> <!--for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,能够有所操做。--> {% empty %} <p>no</p> {% endfor %} {#遍历一个字典#} {% for key,value in dic.items %} <p>{{ key }}--{{ value }}</p> {% endfor %}
注:循环序号能够经过{{forloop}}显示,必须在循环内部用
forloop.counter 当前循环的索引值(从1开始),forloop是循环器,经过点来使用功能 forloop.counter0 当前循环的索引值(从0开始) forloop.revcounter 当前循环的倒序索引值(从1开始) forloop.revcounter0 当前循环的倒序索引值(从0开始) forloop.first 当前循环是否是第一次循环(布尔值) forloop.last 当前循环是否是最后一次循环(布尔值) forloop.parentloop 本层循环的外层循环的对象,再经过上面的几个属性来显示外层循环的计数等
{% if %}
会对一个变量求值,若是它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。
{% if num > 100 %} <p>大于100</p> {% elif num < 100 %} <p>小于100</p> {% else %} <p>等于100</p> {% endif %}
{#Django的模板语言不支持连续判断,即不支持如下写法:#} {#{% if a > b > c %}#} {#...#} {#{% endif %}#}
使用一个简单地名字缓存一个复杂的变量,多用于给一个复杂的变量起别名,当你须要使用一个“昂贵的”方法(好比访问数据库)不少次的时候是很是有用的
例如:
注意等号左右不要加空格。
{% with dic.hobby as hb %} <p>{{ hb }}</p> {% endwith %} {#注意:等号左右不要加空格。#} {% with hb=dic.hobby %} <p>{{ hb }}</p> {% endwith %}
咱们以post方式提交表单的时候,会报错,还记得咱们在settings里面的中间件配置里面把一个csrf的防护机制给注销了啊,自己不该该注销的,而是应该学会怎么使用它,而且不让本身的操做被forbiden,经过这个东西就能搞定。
这个标签用于跨站请求伪造保护,
在页面的form表单里面(注意是在form表单里面)任何位置写上{% csrf_token %},这个东西模板渲染的时候替换成了,隐藏的,这个标签的值是个随机字符串,提交的时候,这个东西也被提交了,首先这个东西是咱们后端渲染的时候给页面加上的,那么当你经过我给你的form表单提交数据的时候,你带着这个内容我就认识你,不带着,我就禁止你,由于后台咱们django也存着这个东西,和你这个值相同的一个值,能够作对应验证是否是我给你的token,存储这个值的东西咱们后面再学,你先知道一下就好了,就像一个咱们后台给这个用户的一个通行证,若是你用户没有按照我给你的这个正常的页面来post提交表单数据,或者说你没有先去请求我这个登录页面,而是直接模拟请求来提交数据,那么我就能知道,你这个请求是非法的,反爬虫或者恶意攻击个人网站,之后将中间件的时候咱们在细说这个东西,可是如今你要明白怎么回事,明白为何django会加这一套防护。
爬虫发送post请求简单模拟:
import requests res = requests.post('http://127.0.0.1:8000/login/',data={ 'username':'chao', 'password':'123' }) print(res.text)
csrf_token绕过csrf的防护机制
#views.py from django.shortcuts import render def token(request): return render(request, 'token.html')
<!--token.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>token</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用户名: <input type="text" name="username"> <button>提交</button> </form> </body> </html>
Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可让您建立一个基本的“骨架”模版,它包含您站点中的所有元素,而且能够定义可以被子模版覆盖的 blocks 。
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 模板 url(r'^base/', views.base), url(r'^menu1/', views.menu1), url(r'^menu2/', views.menu2), url(r'^menu3/', views.menu3), ]
#views.py from django.shortcuts import render def base(request): #模板函数 return render(request, 'base.html') #模板页面 def menu1(request): return render(request, 'menu1.html') def menu2(request): return render(request, 'menu2.html') def menu3(request): return render(request, 'menu3.html')
<!--menu1.html--> {% extends 'base.html' %} {% block content %} menu1 {% endblock %} <!--menu2.html--> {% extends 'base.html' %} {% block content %} menu2 {% endblock %} <!--menu3.html--> {% extends 'base.html' %} {% block content %} menu3 {% endblock %}
能够将经常使用的页面内容如导航条,页尾信息等组件保存在单独的文件中,而后在须要使用的地方,文件的任意位置按以下语法导入便可。
{% include 'navbar.html' %}
#urls.py from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 组件nav url(r'^nav/', views.nav), url(r'^newnav/', views.nav), ]
#views.py from django.shortcuts import render def nav(request): return render(request,'nav.html') def newnav(request): return render(request,'newnav.html')
有个以下的导航栏,nav.html
<!--nav.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>nav</title> <style> body { margin: 0; padding: 0; } .nav { background: red; height: 40px; } </style> </head> <body> <div class="nav"> <a href="">导航</a> <a href="">导航</a> <a href="">导航</a> <a href="">导航</a> <input type="text"> <button>搜索</button> </div> </body> </html>
用了组件的newnav.html
<!--newnav.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {# 组件#} {#能够将经常使用的页面内容如导航条,页尾信息等组件保存在单独的文件中,而后在须要使用的地方,文件的任意位置按以下语法导入便可。#} {% include 'nav.html' %} </body> </html>
组件是提供某一完整功能的模块,如:编辑器组件,QQ空间提供的关注组件 等。 而插件更倾向封闭某一功能方法的函数。 这二者的区别在 Javascript 里区别很小,组件这个名词用得很少,通常统称插件。
1. app应用文件夹中建立一个templatetags文件件,必须是这个名字 2. templatetags文件夹中建立一个 filtertest.py文件,文件名字随便起 3. 建立自定义过滤器 from django import template # register的名字是固定的,不可改变,注册器 register = template.Library() # @register.filter # def filter(v1): #一个参数 # v = v1 + 'yage' # return v @register.filter def filter(v1, v2): # 两个参数 v = v1 + 'yage' + v2 return v 4. 使用 html文件中 {% load 文件名 %} {% load filtertest %} {#一个参数#} {{ v1|filter }} {#两个参数#} {{ v1|filter:' nihao' }} 5. 注意:# filter参数有限制,最多两个参数
1. app应用文件夹中建立一个templatetags文件件,必须是这个名字 2. templatetags文件夹中建立一个 xx.py文件,文件名字随便起 3. 建立自定义标签 from django import template # register的名字是固定的,不可改变,注册器 register = template.Library() # simple_tag和自定义filter相似,只不过接收更灵活的参数,没有个数限制。 # 注意:filter能够用在if、for等语句后,simple_tag不能够 @register.simple_tag def simple_tag(vv): v = 'yagehaha' + vv return v 4. 使用 html文件中 {% load 文件名 %} {#simple_tag标签#} <p>{% simple_tag v1 %}</p> 5. #能够传多个参数
1. app应用文件夹中建立一个templatetags文件件,必须是这个名字 2. templatetags文件夹中建立一个 xx.py文件,文件名字随便起 3. 建立自定义inclusion_tag # 多用于返回html代码片断 做为一个组件 @register.inclusion_tag('inclusion_tag.html') # 将inclusion_tag.html里面的内容用下面函数的返回值渲染,而后做为一个组件同样,加载到使用这个函数的html文件里面 def inclusion_tag(ll): # 参数能够传多个进来 return {'date': ll} # 这里能够穿多个值,和render的感受是同样的{'data1':data1,'data2':data2....} # views 的 ll 传给 index.html 中的{% inclusion_tag ll%}, # inclusion_tag 接收参数到filtertest.py 的 def inclusion_tag(ll), # 将参数ll传给@register.inclusion_tag('inclusion_tag.html') 进行模板渲染。 4.使用 {% inclusion_tag ll%}
js、css、img等都叫作静态文件,那么关于django中静态文件的配置,咱们就须要在settings配置文件里面写上这写内容:
1 在项目中建立一个文件夹,好比叫jingtaiwenjian # STATIC_URL = '/xxx/' #别名,随便写名字,可是若是你更名字,别忘了前面页面里面若是你是经过/xxx/bootstrap.css的时候,若是这里的别名你改为了/static/的话,你前端页面的路径要改为/static/bootstrap.css。因此咱们都是用下面的load static的方式来使用静态文件路径 2 STATIC_URL = '/static/' #别名 3 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'jingtaiwenjian'), #注意别忘了写逗号,第二个参数就是项目中你存放静态文件的文件夹名称 ]
目录:别名也是一种安全机制,浏览器上经过调试台你可以看到的是别名的名字,这样别人就不能知道你静态文件夹的名字了,否则别人就能经过这个文件夹路径进行攻击。
前端页面引入静态文件的写法,由于别名也可能会修改,因此使用路径的时候经过load static来找到别名,经过别名映射路径的方式来获取静态文件
{% load static %} <img src="{% static "images/hi.jpg" %}" alt="Hi!" /> 引用JS文件时使用: {% load static %} <script src="{% static "mytest.js" %}"></script> 某个文件多处被用到能够存为一个变量 {% load static %} {% static "images/hi.jpg" as myphoto %} <img src="{{ myphoto }}"></img>
{% load static %} <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" /> 或者 {% load static %} {% get_static_prefix as STATIC_PREFIX %} <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" /> <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />