模板
一、模板语法之变量
- {{ comment.create_time|date:"Y-m-d H:i:s" }}
- {{ bio|truncatewords:"30" }}
- {{ my_list|first|upper }}
- {{ name|lower }}
- {{ forloop.counter }}
- {{ forloop.first }}
- {{ forloop.last }}
在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法: {{var_name}}
1
2
3
4
5
6
|
<h4>{{s}}< / h4> <h4>列表:{{ l. 0 }}< / h4> <h4>列表:{{ l. 2 }}< / h4> <h4>字典:{{ dic.name }}< / h4> <h4>日期:{{ date.year }}< / h4> <h4>类对象列表:{{ person_list. 0.name }}< / h4> |
二、模板之过滤器
语法:{{obj|filter__name:param}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
default:如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如: {{ value|default: "nothing" }} length:返回值的长度。它对字符串和列表都起作用。例如: {{ value|length }} 如果 value 是 [ ‘a‘ , ‘b‘ , ‘c‘ , ‘d‘ ],那么输出是 4 。 filesizeformat:将值格式化为一个 “人类可读的” 文件尺寸 (例如 ‘13 KB‘ , ‘4.1 MB‘ , ‘102 bytes‘ , 等等)。例如: {{ value|filesizeformat }} 如果 value 是 123456789 ,输出将会是 117.7 MB。 date:如果 value = datetime.datetime.now() {{ value|date: "Y-m-d" }} slice :如果 value = "hello world" {{ value| slice : "2:-1" }} truncatechars: 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。 参数:要截断的字符数 {{ value|truncatechars: 9 }} safe:Django的模板中会对HTML标签和JS等语法标签进行自动转义,这样是为了安全。如果不希望HTML元素被转义,可以这样: value = "<a href=" ">点击</a>" {{ value|safe}} |
这里简单介绍一些常用的模板的过滤器,更多详见
三、模板之标签
标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。
1、for标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
""" 遍历每一个元素: {% for person in person_list %} <p>{{ person.name }}</p> {% endfor %} 可以利用{% for obj in list reversed %}反向完成循环。 遍历一个字典: {% for key,val in dic.items %} <p>{{ forloop.counter }} {{ key }}:{{ val }}</p> {% endfor %} 注:循环序号可以通过{{ forloop }}显示 forloop.counter The current iteration of the loop (1-indexed) forloop.counter0 The current iteration of the loop (0-indexed) forloop.revcounter The number of iterations from the end of the loop (1-indexed) forloop.revcounter0 The number of iterations from the end of the loop (0-indexed) forloop.first True if this is the first time through the loop forloop.last True if this is the last time through the loop """ |
2、for ... empty
1
2
3
4
5
6
|
<! - - for 标签带有一个可选的{ % empty % } 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。 - - > { % for person in person_list % } <p>{{ forloop.counter0 }} {{ person.name }} , {{ person.age }}< / p> { % empty % } <p>列表为空< / p> { % endfor % } |
3、if 标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<! - - 注意: filter 可以用在 if 等语句后,simple_tag不可以 - - > { % if i|multi_fliter: 10 > 100 % } <p> 100 < / p> { % else % } <p>{{ i }}< / p> { % endif % } <! - - 多分支 - - > { % if num > 100 or num < 0 % } <p>无效< / p> { % elif num > 80 and num < 100 % } <p>优秀< / p> { % else % } <p>凑活吧< / p> { % endif % } |
4、with
1
2
3
4
5
|
<! - - 使用一个简单地名字缓存一个复杂的变量 - - > { % with person_list. 1.name as n % } {{ n }} {{ n }} { % endwith % } |
5、csrf_token
1
2
3
4
5
|
<form action = " " method=" post"> { % csrf_token % } <! - - 这个标签用于跨站请求伪造保护 - - > < input type = "text" name = "user" > < input type = "submit" > < / form> |
四、自定义标签和过滤器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
""" 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不可以 """ #settings.py INSTALLED_APPS = [ ‘django.contrib.admin‘ , ‘django.contrib.auth‘ , ‘django.contrib.contenttypes‘ , ‘django.contrib.sessions‘ , ‘django.contrib.messages‘ , ‘django.contrib.staticfiles‘ , "app01" , #配置当前app ] # app01.templatetags.my_tags.py from django import template from django.utils.safestring import mark_safe register = template.Library() # register的名字是固定的,不可改变 @register . filter #自定义过滤器最多2个参数 def multi_fliter(v1, v2): return v1 * v2 @register .simple_tag #自定义标签,没有参数个数限制 def multi_tag(v1, v2, v3): return v1 * v2 * v3 @register .simple_tag def my_input( id , arg): result = "<input type=‘text‘ id=‘%s‘ class=‘%s‘ />" % ( id , arg,) return mark_safe(result) #模板中: """ {% load my_tags %} <!--注意:这块更改过要重启项目--> # num = 8 <p>{{ num|multi_fliter:20 }}</p> <p>{% multi_tag 7 9 6 %}</p> <!--注意:filter可以用在if等语句后,simple_tag不可以--> {% if num|multi_fliter:10 > 100 %} <p>100</p> {% else %} <p>{{ num }}</p> {% endif %} """ |
五、模板之inclusion_tag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# app01.templatetags.my_tags.py from django import template from django.db.models import Count from app01 import models register = template.Library() @register .simple_tag def multi_tag(x,y): return x * y @register .inclusion_tag( "classification.html" ) def get_classification_style(username): user = models.UserInfo.objects. filter (username = username).first() blog = user.blog cate_list = models.Category.objects. filter (blog = blog).values( "pk" ).annotate(c = Count( "article__title" )).values_list( "title" , "c" ) tag_list = models.Tag.objects. filter (blog = blog).values( "pk" ).annotate(c = Count( "article" )).values_list( "title" , "c" ) date_list = models.Article.objects. filter (user = user).extra(select = { "y_m_date" : "date_format(create_time,‘%%Y/%%m‘)" }).values( "y_m_date" ).annotate(c = Count( "nid" )).values_list( "y_m_date" , "c" ) return { "blog" :blog, "cate_list" :cate_list, "date_list" :date_list, "tag_list" :tag_list} #模板中:使用 """ <div class="col-md-3 menu"> {% load my_tags %} {% get_classification_style username %} </div> """ #templates.classification.html """ <div> <div class="panel panel-warning"> <div class="panel-heading">我的标签</div> <div class="panel-body"> {% for tag in tag_list %} <p><a href="/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p> {% endfor %} </div> </div> <div class="panel panel-danger"> <div class="panel-heading">随笔分类</div> <div class="panel-body"> {% for cate in cate_list %} <p><a href="/{{ username }}/category/{{ cate.0 }}">{{ cate.0 }}({{ cate.1 }})</a></p> {% endfor %} </div> </div> <div class="panel panel-success"> <div class="panel-heading">随笔归档</div> <div class="panel-body"> {% for date in date_list %} <p><a href="/{{ username }}/archive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a></p> {% endfor %} </div> </div> </div> """ |
六、模板继承 (extend)
- 不能在一个模版中定义多个相同名字的 block 标签。
- 为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:{% block content %}...{% endblock content %}
- 子模版不必定义全部父模版中的blocks
- {% extends ‘base.html‘ %}
1、制作模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<! - - 模版 base.html - - > <!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > { % block title % } <title>base< / title> { % endblock % } { % block css % } { % endblock % } < / head> <body> <div class = "header" >< / div> <div class = "container" > <div class = "row" > <div class = "col-md-3" > { % include ‘left1.html‘ % } <! - - 引入小组件 - - > { % include ‘ad.html‘ % } <! - - 引入小组件 - - > < / div> <div class = "col-md-9" > { % block con % } <h4>content< / h4> { % endblock content % } <! - - 更好的可读性 - - > < / div> < / div> < / div> { % block js % }{ % endblock % } < / body> < / html> |
2、继承模板
1
2
3
4
5
6
7
8
9
10
11
12
|
{ % extends ‘base.html‘ % } <! - - 它必须是模版中的第一个标签。 - - > { % block title % } <title>orders< / title> { % endblock % } { % block con % } {{ block. super }} <! - - 获取模板中con的内容 - - > <h4>订单< / h4> { % endblock con % } <! - - order.html - - > |
七、模板多对多调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
class Student(models.Model): name = models.CharField(max_length = 128 ) class Course(models.Model): name = models.CharField(max_length = 128 ) students = models.ManyToManyField( ‘Student‘ ) 正向查询: 从course往student查 def test(request): course = models.Course.objects.get(pk = 1 ) return render(request, ‘course.html‘ , locals ()) 获取了 id 为 1 的course对象,并将它传递给course.html模版,模版代码如下: { % for student in course.students. all % } <p>{{ student.name }}< / p> { % endfor % } 首先通过course.students. all ,查寻到course对象关联的students对象集,然后用 for 标签循环它,获取每个student对象,再用student模型的定义,访问其各个字段的属性。 反向查询: 从student往course查,假设有如下的视图: def test2(request): student = models.Student.objects.get(pk = 1 ) return render(request, ‘student.html‘ , locals ()) 获取了 id 为 1 的student对象,并将它传递给student.html模版,模版代码如下: { % for course in student.course_set. all % } {{ course.name }} { % endfor % } 通过student.course_set. all ,反向获取到student实例对应的所有course对象,然后再 for 标签循环每个course,调用course的各种字段属性。 #### 对于外键ForeignKey,其用法基本类似。只不过正向是obj.fk,且只有 1 个对像,不是集合。反向则是obj.fk_set,类似多对多。 |
八、内置模板标签
标签 | 说明 |
---|---|
autoescape | 自动转义开关 |
block | 块引用 |
comment | 注释 |
csrf_token | CSRF令牌 |
cycle | 循环对象的值 |
debug | 调试模式 |
extends | 继承模版 |
filter | 过滤功能 |
firstof | 输出第一个不为False的参数 |
for | 循环对象 |
for … empty | 带empty说明的循环 |
if | 条件判断 |
ifequal | 如果等于 |
ifnotequal | 如果不等于 |
ifchanged | 如果有变化,则.. |
include | 导入子模版的内容 |
load | 加载标签和过滤器 |
lorem | 生成无用的废话 |
now | 当前时间 |
regroup | 根据对象重组集合 |
resetcycle | 重置循环 |
spaceless | 去除空白 |
templatetag | 转义模版标签符号 |
url | 获取url字符串 |
verbatim | 禁用模版引擎 |
widthratio | 宽度比例 |
with | 上下文变量管理器 |
九、内置过滤器总览
为模版过滤器提供参数的方式是:过滤器后加个冒号,再紧跟参数,中间不能有空格! 目前只能为过滤器最多提供一个参数!
过滤器 | 说明 |
---|---|
add | 加法 |
addslashes | 添加斜杠 |
capfirst | 首字母大写 |
center | 文本居中 |
cut | 切除字符 |
date | 日期格式化 |
default | 设置默认值 |
default_if_none | 为None设置默认值 |
dictsort | 字典排序 |
dictsortreversed | 字典反向排序 |
divisibleby | 整除判断 |
escape | 转义 |
escapejs | 转义js代码 |
filesizeformat | 文件尺寸人性化显示 |
first | 第一个元素 |
floatformat | 浮点数格式化 |
force_escape | 强制立刻转义 |
get_digit | 获取数字 |
iriencode | 转换IRI |
join | 字符列表链接 |
last | 最后一个 |
length | 长度 |
length_is | 长度等于 |
linebreaks | 行转换 |
linebreaksbr | 行转换 |
linenumbers | 行号 |
ljust | 左对齐 |
lower | 小写 |
make_list | 分割成字符列表 |
phone2numeric | 电话号码 |
pluralize | 复数形式 |
pprint | 调试 |
random | 随机获取 |
rjust | 右对齐 |
safe | 安全确认 |
safeseq | 列表安全确认 |
slice | 切片 |
slugify | 转换成ASCII |
stringformat | 字符串格式化 |
striptags | 去除HTML中的标签 |
time | 时间格式化 |
timesince | 从何时开始 |
timeuntil | 到何时多久 |
title | 所有单词首字母大写 |
truncatechars | 截断字符 |
truncatechars_html | 截断字符 |
truncatewords | 截断单词 |
truncatewords_html | 截断单词 |
unordered_list | 无序列表 |
upper | 大写 |
urlencode | 转义url |
urlize | url转成可点击的链接 |
urlizetrunc | urlize的截断方式 |
wordcount | 单词计数 |
wordwrap | 单词包裹 |
yesno | 将True,False和None,映射成字符串‘yes’,‘no’,‘maybe’ |