模板
一、模板语法之变量
- {{ 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’ |