模板
一、模板语法之变量
- {{ 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 loopforloop.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.py4、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py5、使用simple_tag和filter(如何调用)注意:filter可以用在if等语句后,simple_tag不可以"""#settings.pyINSTALLED_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.pyfrom django import templatefrom django.utils.safestring import mark_saferegister = 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_tagdef 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.pyfrom django import templatefrom django.db.models import Countfrom app01 import modelsregister=template.Library()@register.simple_tagdef 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’ |