Django模板层
模板层的主要任务就是如何将页面呈现给用户,用户能看到的所有东西都是属于模板层进行呈现的。
HTML
文件就是模板,模板是会先经过渲染,再呈现给用户。
学习模板层主要有以下两点:
变量相关或处理均使用
{{}}
,即模板变量。逻辑相关或处理均使用
{%%}
,即模板标签。
模板变量传值
其实在聊Django
视图层的时候介绍的render()
方法中就允许将视图函数中的变量传递给模板。
模板中使用{{name}}
即可完成调用。
def test(request):
username = "云崖先生"
return render(request,"test.html",locals())
{{username}}
传值类型
Python
中所有基本数据类型均可以进行模板传递,但是函数、类等可调用类型会出现一些令人意外的情况。
注意:可调用类型传递时会自动加括号调用,并将返回值进行渲染(如果没有返回值则为
None
),但是不支持参数的传递。
后端返回:
def test(request):
STR = "云崖先生"
INT = 100
FLOAT = 11.11
BOOL = True
DICT = {"v1":"k1"}
SET = {"1","2","3"}
TUPLE = (1,2,3)
LIST = [1,2,3,4]
def func():
return "function"
class T1(object):
pass
return render(request,"test.html",locals())
模板接收:
{{STR}}
{{INT}}
{{FLOAT}}
{{BOOL}}
{{DICT}}
{{SET}}
{{TUPLE}}
{{LIST}}
{{func}}
{{T1}}
渲染结果:
云崖先生
100
11.11
True
{'v1': 'k1'}
{'1', '2', '3'}
(1, 2, 3)
[1, 2, 3, 4]
function
.T1 object at 0x000001C1E00ACB38>
元素取出
无论后端的变量是list
或者dict
,均可使用.
语法进行取值。
传值:
def test(request):
DICT = {"hobby":["basketball","football","volleyball"]}
return render(request,"test.html",locals())
取值:
{{DICT.hobby.2}}
结果:
volleyball
模板变量过滤
由于后端的函数模板中使用函数无法传递参数,所以提供自带的过滤器进行操作。
过滤器有非常多的功能,大概有六十多种过滤器提供使用,这里只介绍常用的。
使用示例
以下举例常用的模板过滤器
过滤器 | 描述 |
---|---|
{{v1|length}} | 获取v1的长度 |
{{v1|default:v2}} | 如果v1为真,则使用v1,否则使用v2 |
{{v1|filesizeformat}} | v1必须是int类型,对其进行KB、MB、GB、TB 等进制之间的转换 |
{{v1|date:"Y-m-d X"}} | v1必须是时间类型,对其进行自定义格式化 |
{{v1|slice:"start:stop:step"}} | v1必须是可通过索引取值的类型,对其进行切片 |
{{v1|truncatechars:num}} | v1必须是可通过索引取值的类型,对其截取指定长度的字符(包含三个. ) |
{{v1|truncatewords:num}} | v1必须是字符串类型,对其进行截取特点数量的单词,以空格分隔(不包含. ) |
{{v1|cut:'v2'}} | 移除v1中特定的字符v2 |
{{v1|join:'v2'}} | 使用v2对v1进行拼接 |
{{v1|add:v2}} | v1与v2进行相加,如都是int则为加法,如都是str则为拼接 |
{{v1|safe}} | 识别v1中的HTML代码并进行渲染(默认不会进行渲染) |
后端返回:
def test(request):
import datetime
v_1 = "12345"
v_2 = False
v_3 = 10240
v_4 = datetime.datetime.now()
v_5 = ["一","二","三","四","五","六","七"]
v_6 = "abcdefghijklmn"
v_7 = "HELLO WORD HELLO DJANGO"
v_8 = "ABC$$$"
v_9 = "QWETYU"
v_10 = 10
v_11 = "标题一"
return render(request,"test.html",locals())
模板接收加过滤:
{{v_1|length}}
{{v_2|default:1}}
{{v_3|filesizeformat}}
{{v_4|date:"Y-m-d h:m:s"}}
{{v_5|slice:"1:4:2"}}
{{v_6|truncatechars:6}}
{{v_7|truncatewords:3}}
{{v_8|cut:"$"}}
{{v_9|join:"---"}}
{{v_10|add:10}}
{{v_11|safe}}
渲染结果:
后端渲染
默认的,后端如果返回HTML
代码模板层是不会进行渲染的,这是为了防止XSS
攻击。
但是如果使用mark_safe()
进行包裹,则会进行渲染。
def test(request):
from django.utils.safestring import mark_safe # 导入模块
res = "不会渲染"
res_safe = mark_safe("会渲染")
return render(request,"test.html",locals())
{{res}}
{{res_safe}}
模板标签分支
基本使用
模板中支持对{% if %}、{% else %}、{% elif %}
进行使用,与Python
中逻辑一致。
注意:判断完成后要使用
{% endif %}
进行结束判断的标志
{% if user %}
有内容
{% else %}
无内容
{% endif %}
模板标签循环
基本使用
模板中支持{% for %}
来进行操作。
注意:循环完成后要使用
{% endfor %}
进行结束循环的标志
li = ["A","B","C"]
{% for row in li %}
{{row}}
{% endfor %}
A
B
C
forloop
{{forloop}}
记录了一些循环的信息。
如下所示:
li = ["A","B","C"]
{% for row in li %}
{{forloop}}
{% endfor %}
不可循环
如果一个迭代对象为空,则不可循环。此时可以使用{% empty %}
进行操作
li = []
{% for row in li %}
不为空
{% empty %}
迭代对象为空
{% endfor %}
键值方法
在循环中,可以对被遍历的对象使用keys、values、items
进行操作。
这与Python
中是一样的。
dic = {"name":"云崖","age":"18","gender":"男",}
{% for key in dic.keys %}
{{key}}
{% endfor %}
{% for value in dic.values %}
{{value}}
{% endfor %}
{% for kv in dic.items %}
{{kv}}
{% endfor %}
----------------
name
age
gender
----------------
云崖
18
男
----------------
('name', '云崖')
('age', '18')
('gender', '男')
模板标签别名
可以使用{% with %}
配合as
对嵌套复杂的单项数据做一个别名。方便后续进行拿出,更推荐与循环进行配套使用。
li = [
{"username":"Yunya"},
{"username":"Jack"},
{"username":"Tom"},
]
----------------
{% for row in li %}
{% with row.username as data %}
{{data}}
{% endwith %}
{% endfor %}
----------------
Yunya
Jack
Tom
自定义系列
所有的,自定义都需要完成以下三步骤:
1.在
APP
中创建templatetags
文件夹,必须叫这个名字2.在该文件夹下创建一个
py
文件,可以是任意名字3.导入一个模块,并写一句话
from django import template
register = template.Library()
自定义过滤器
先完成上面三步,再进行过滤器的创建。
自定义过滤器的作用就是丰富内置的过滤器,完成你的需求。
注意:过滤器的调用是
{{ v1|filter:v2 }}
,过滤器最多只能传递两个参数,且第一个参数在|
左边,第二个参数传递的格式必须是过滤器名字:
右边的参数。
自定义过滤器全步骤:
# app01/templatetags/tags.py
from django import template
register = template.Library()
@register.filter(name="f1") # 在使用时,使用的是这个名字。函数名可以随便取。注意一定要关键字传参
def f1(left, right): # left 代表斜杠左边的值,right代表斜杠右边的值
return left + right
基本使用:
{% load tags %}
{{1|f1:2}}
{% t1 1 2 3%}
自定义inclusion_tag
自定义inclusion_tag
与上面两个都不太一样,它返回的是一个局部页面,当你的项目中有很多网页中都有相同的一部分网页结构,则使用自定义inclusion_tag
来完成。
还是需要先完成上面三个步骤。
# app01/templatetags/tags.py
from django import template
register = template.Library()
@register.inclusion_tag("common.html") # 去根目录找templates文件夹下的common.html文件
def common_html(username): # 注意,这里调用是函数名,而不是上面指定的名字了
user = username
return locals() # 返回当前命名空间中所有变量名
# 项目根目录/templats/common.html
当前登录:{{user}}
# 可以拿到 common_html 函数中的所有变量名了
点击注销
# 被渲染的模板
{% load tags %}
{% common_html "云崖" %}
模板继承引入
模板继承
模板继承是全栈开发里面Django
所提供的非常牛逼的一个功能,它允许你一套HTML
模板能被其他模板进行继承并修改一些特定区域的内容。
# 项目根目录/templats/common.html
{% block left %}
{% endblock %}
============================
# 项目根目录/templats/other.html
{% extends 'common.html' %}
{% block left %}
{% endblock %}
接下来看一下演示代码就知道了。
这里放一套公用的左右布局页面
# 项目根目录/templats/common.html
Document
{% block CSS %}
{% endblock %}
{% block right %}
{% endblock %}
{% block Js %}
{% endblock %}
# 项目根目录/templats/其他页面.html
{% extends 'common.html' %}
{% block left %}
Subheading
Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.
Subheading
Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.
Subheading
Maecenas sed diam eget risus varius blandit sit amet non magna.
{% endblock %}
{% block css %}
{% endblock %}
{% block js %}
{% endblock %}
{% endblock %}
{% block right %}
模板引入
模板引入是在一个HTML
中引入一段公用的HTML
代码。
# 项目根目录/templats/common.html
公用咯
============================
# 项目根目录/templats/other.html
{include "common.html"}