将页面的设计和Python的代码分离开会更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式。
先看一个简单的示例:
项目名\app名\views.py
from django.shortcuts import render, HttpResponse, redirect
import datetime
def current_date(request):
now = datetime.datetime.now()
return render(request, 'current_datetime.html', {'current_date': str(now)[:19]})
项目名\templates\current_datetime.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"></html>
<title>Title</title>
</head>
<body>
<p>This is 模板语法</p>
现在时刻是:<h4>{{current_date}}</h4>
</body>
1 模板语法之变量
在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法如下:
项目名\app名\views.py
def index(request):
'''
模板渲染语法由render渲染
name = "CY"
age = 35
students = ["A","B","C"] # 列表
info = {"name": "CY", "age": "88"} # 字典
class Animal(object):
def __init__(self, name, age):
self.name = name
self.age = age
def running(self):
print("running")
cy = Animal("cy", 99)
ll = Animal("ll", 98)
person_list = [cy, ll]
return render(request, "index.html", locals()) # locals 返回包含当前范围的局部变量的字典。
项目名\templates\index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Mysite</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>This is 模板语法</p>
<h4>1.渲染各种数据类型</h4>
<p>姓名 {{name}} 年龄 {{age}}</p>
<p>{{ students.0 }}</p> <!-- 查询 列表-->
<p>{{ students.1 }}</p> <!-- 查询 列表-->
<p>{{ info }}</p> <!-- 查询 字典-->
<p>{{ info.name }}</p>
<p>{{ info.age }}</p>
<p>{{ person_list.0.name }}</p>
注意:句点符也可以用来引用对象的方法(无参数方法),例如:
{{ info.name.upper }}
index页面结果:2 模板之过滤器
语法:
{{obj|filter__name:param}}
项目名\app名\views.py
def index(request):
now = datetime.datetime.now()
book_list = ["活着", "平凡的世界", "解忧杂货铺"] # 如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。
file_size = 123123123
article = "Function views: 1,Add an import: from my_app import views, 2. Add a URL to urlpatterns"
link = "<a href='http://www.baidu.com'>点我</a>"
tag = "<script>alert(123)</script>"
return render(request, "index.html", locals()) # locals 返回包含当前范围的局部变量的字典。
项目名\templates\index.html
<h4>2.过滤器</h4>
<P>{{ now }}</P> <!-- 无过滤器显示时间格式 -->
<P>{{ now|date:"Y-m-d" }}</P> <!-- date -->
<p>{{ book_list|length }}</p> <!-- length 返回值的长度。它对字符串和列表都起作用 -->
<p>{{ book_list|default:"无符合条件的目录"}}</p> <!-- default -->
<p>{{ file_size|filesizeformat }}</p> <!-- filesizeformat 将值格式化为一个可读的文件尺寸 -->
<p>{{ article|truncatechars:7 }}</p> <!-- truncatechars 如果字符串字符多于指定的字符数量,将会被截断。截断的字符数量也包括省略号,以(“...”)结尾。-->
<p>{{ article|truncatewords:5 }}</p> <!-- 截断单词,5个单词。以省略号序列(“...”)结尾。-->
<p>{{ link|safe }}</p> <a href='http://www.baidu.com'>点我</a> <!--如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义 -->
<p>{{ tag|safe }}</p> <!-- 页面标签会提示安全弹窗-->
index页面结果:
关于safe :
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。
3 模板之标签
标签看起来像是这样的: {% tag %}。
标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。
一些标签需要 开始 和 结束 标签
例如:{% tag %} …标签 内容 … {% endtag %}
<h4>3.标签</h4>
<!--for标签-->
<ul>
{% for book in book_list %} <!-- 遍历每一个元素 -->
<li> {{ book }} {{ forloop.counter }}</li>
{% endfor %}
</ul>
<!--if 标签-->
{% if age > 100 %} <!-- 对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。-->
<p>100</p> <!-- if 成立,渲染此标签-->
{% else %}
<p>{{ age }}</p> <!-- if 不成立,渲染此标签 实际为 age = 35-->
{% endif %}
<!-- with标签 -->
<p> {{ person_list.1.name }}</p>
<p>
{% with name=person_list.1.name %} <!-- 注意:name=xxx 中间不允许有空格 否则会报错!'with' expected at least...-->
{{ name }}
{% endwith %}
</p>
index页面结果:
3.标签
活着 1
平凡的世界 2
解忧杂货铺 3
35
ll
ll
知识拓展:csrf_token 标签
防止跨站攻击:
表单:在 Form 表单中添加一个隐藏的的字段,值是 csrf_token。
原理:在浏览器访问网站A时,网站A设置cookie会增加随机值csrf_token,这个值是随机的。返回给浏览器时,cookie会储存在浏览器,同时会把csrf_token传给表单里面的隐藏字段。所以当浏览器用自己的表单时会自带csrf_token,网站A取到这个值和cookie里的csrf_token一致就通过。而网站B里面的表单没有这个值,所以不能通过,这样就阻止了恶意攻击。非表单也是这样的原理。
目的是防御CSRF攻击。
Token就是令牌,最大的特点就是随机性,不可预测。
示例如下:
一、项目名\templates\login.html
<!--csrf_token 标签 :这个标签用于跨站请求伪造保护-->
...
<body>
<form action="/login/" method="post">
{% csrf_token %} <!-- 这个标签用于跨站请求伪造保护 -->
<!--此标签必须放在 form 表单标签内,否则报错-->
<!--网页 Response 信息中多了一行 :<input type='hidden' name='csrfmiddlewaretoken' value='6nfubmaDIrRUe20GhFyqZDEGEqQyZ9XZ' />-->
用户名 <input type="text" name="user">
密码 <input type="password" name="pwd">
<input type="submit">
</form>
</body>
二、项目名\settings.py
MIDDLEWARE_CLASSES = (
# 'django.middleware.csrf.CsrfViewMiddleware',
# 确保此行代码关闭,用于演示不加认证防御情况下,可轻易获取内容。
)
三、确认 requests 已安装,然后导入requests模块
项目名\app名\tests.py
# 以下代码用于演示
import requests
res = requests.post("http://127.0.0.1:8000/login/",
data={
"user":"cy",
"pwd":"123"
})
print(res.text)
最后运行 tests.py 文件,输出结果便是index.html的页面内容。
"D:\Program Files\Mypython\Myvenv\Myvenv_Dj1.8\Scripts\Python.exe" ...
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Mysite</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/commons.css" />
</head>
<body>
<p>This is 模板语法</p>
<h4>1.渲染各种数据类型</h4>
...
4 自定义标签和过滤器
1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
2、在app中创建templatetags模块(模块名只能是templatetags)
3、创建任意 .py 文件,如:my_tags.py
4、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py
5、使用simple_tag和filter(如何调用)
注意:filter可以用在 if 等语句后,simple_tag 不可以
5 模板继承 (extend)
Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。