Django - 模板
- 作为一个网络框架,Django 需要一种方便的方式来动态生成 HTML。最常见的方法是依靠模板。一个模板包含了所需 HTML 输出的静态部分,以及一些特殊的语法,描述了如何插入动态内容。关于使用模板创建 HTML 页面的实战例子,请看 教程 3。
- 一个 Django 项目可以配置一个或多个模板引擎(如果你不使用模板,甚至可以不配置模板)。Django 内置了自己的模板系统后端,创造性地称为 Django 模板语言(DTL),以及流行的替代版本 Jinja2。其他模板语言的后端可以从第三方获得。你也可以编写自己的自定义后端,参见:自定义模板后端
- Django 定义了一个标准的API,用于加载和渲染模板,而不考虑后端。加载包括为给定的标识符找到模板并对其进行预处理,通常是将其编译成内存中的表示形式。渲染是指将上下文数据插入模板,并返回结果字符串。
- Django 模板语言 是 Django 自己的模板系统。在 Django 1.8 之前,它是唯一的内置选项。它是一个很好的模板库,尽管它是相当有主见的,并且有一些特殊的地方。如果你没有迫切的理由选择另一个后端,你应该使用 DTL,特别是当你正在编写一个可插拔的应用程序,并且你打算发布模板时。Django 的 contrib 应用如果包含模板,比如 django.contrib.admin,就使用 DTL。
- 由于历史原因,模板引擎的通用支持和 Django 模板语言的实现都在
django.template
的命名空间中。
- 模板引擎是通过
TEMPLATES
进行配置。这是一个配置列表,每个引擎都有一个。默认值为空。startproject
命令生成的settings.py
定义了一个更有用的值:1
2
3
4
5
6
7
8
9
10TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
# ... some options here ...
},
},
] BACKEND
是实现 Django 模板后端 API 的模板引擎类的点分隔 Python 路径。内置的后端有django.template.backends.django.DjangoTemplates
和django.template.backends.jinja2.Jinja2
。- 由于大多数引擎都是从文件中加载模板,因此每个引擎的顶层配置都包含两个常见的配置:
- 虽然不常见,但可以使用不同的选项配置同一后端的多个实例。 在这种情况下,你应该为每个引擎定义一个唯一的
NAME
。 OPTIONS
包含特定于后端的配置。
-
模板
-
概述
- 模板是一个文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV 等)。
- 一个模板包含 变量 和 标签,前者在模板被执行时被替换为值,后者控制模板的逻辑。
-
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16{% extends "base_generic.html" %}
{% block title %}{{ section.title }}{% endblock %}
{% block content %}
<h1>{{ section.title }}</h1>
{% for story in story_list %}
<h2>
<a href="{{ story.get_absolute_url }}">
{{ story.headline|upper }}
</a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}
-
-
变量
-
概述
- 变量看起来像这样:
{{ variable }}
。 当模板引擎遇到一个变量时,它会计算该变量并将其替换为结果。 变量名称由字母数字字符和下划线(_
)的任意组合组成,但不能以下划线开头,也不能是数字。 点 (.
) 也出现在可变部分中,尽管它具有特殊含义,如下所示。 重要的是,变量名中不能有空格或标点符号。 - 使用点号(
.
)来访问一个变量的属性。
- 变量看起来像这样:
-
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25from datetime import datetime
from django.shortcuts import render
class Movie:
def __init__(self, name, director):
self.name = name
self.director = director
def __str__(self):
return self.name
# Create your views here.
def index(request):
name = 'admin'
dtime = datetime.now()
movies = ['僵尸先生', '速度与激情8', '中国机长', '我和我的祖国', '复联4']
stars = {'boy': '蔡徐坤', 'girl': '乔碧萝'}
movie_obj = Movie('攀登者', '李仁港')
return render(request, 'index.html', context={
'name': name, 'dtime': dtime, 'num': 100, 'score': 7.8, 'movies': movies, 'stars': stars, 'movie_obj': movie_obj
})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
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
欢迎:{{ name }},当前时间是:{{ dtime }}
<br>
访问量:{{ num }},评分:{{ score }}
<hr>
喜欢的电影:
{#{{ movies.3 }}#}
<ul>
{% for movie in movies %}
<li>{{ movie }}</li>
{% endfor %}
</ul>
<hr>
喜欢的网红:
男:{{ stars.boy }}
女:{{ stars.girl }}
<hr>
电影名称:{{ movie_obj.name }}
导演:{{ movie_obj.director }}
</body>
</html>
-
-
过滤器
-
概述
- 你可以通过使用 过滤器 修改显示的变量。
- 过滤器是这样的:
{{ name|lower }}
。这将显示lower
过滤器过滤后的{{ name }}
变量的值,该过滤器将文本转换为小写。使用管道(|
)来应用过滤器。 - 过滤器可以“链式的”。一个过滤器的输出被应用到下一个过滤器。
{{ text|escape|linebreaks }}
是一个常用的成语,用于转义文本内容,然后将换行符转换为<p>
标签。 - 有些过滤器需要参数。一个过滤器的参数是这样的:
{{ bio|truncatewords:30 }}
。这将显示bio
变量的前 30 个字。 - 包含空格的过滤器参数必须加引号;例如,要连接一个包含逗号和空格的列表,你可以使用
{{ list|join:", " }}
。 - Django 提供了大约 60 个内置的模板过滤器。你可以在 内置过滤器参考 中阅读它们。
-
default
如果一个变量为 false 或空,使用给定的默认值。否则,使用变量的值。例如:
1
{{ value|default:"nothing" }}
如果
value
没有提供或者为空,那么他将显示为“nothing
”。 -
length
返回值的长度。这对字符串和列表都有效。例如:
1
{{ value|length }}
如果
value
为['a', 'b', 'c', 'd']
, 那么他将被显示为4
。 -
filesizeformat
以“人类可读”的文件大小格式化该值(即
'13 KB'
、'4.1 MB'
、'102 bytes'
等)。例如:1
{{ value|filesizeformat }}
如果
value
是 123456789,则输出为117.7 MB
。 -
lower
将一个字符串转换为全小写。
1
{{ value|lower }}
如果
value
是Totally LOVING this Album!
,则输出为totally loving this album!
。 -
upper
将一个字符串转换为全大写。
1
{{ value|upper }}
如果
value
是"Joel is a slug"
,则输出将是"JOEL IS A SLUG"
。 -
title
通过使单词以大写字母开头,其余字符以小写字母开头,将字符串转换为大写字母。这个标签不会努力让 “琐碎的单词” 保持小写。
1
{{ value|title }}
如果
value
是"my FIRST post"
,则输出将是"My First Post"
。 -
capfirst
将值的第一个字符大写。如果第一个字符不是字母,这个过滤器就没有效果。
1
{{ value|capfirst }}
如果
value
是"django"
,则输出为"Django"
。 -
floatformat
当不使用参数时,将浮点数四舍五入到小数点后一位——但只在有小数部分要显示的情况下。
value
模板 输出 34.23234
{{ value|floatformat }}
34.2
34.00000
{{ value|floatformat }}
34
34.26000
{{ value|floatformat }}
34.3
如果与数字整数参数一起使用,
floatform
将一个数字四舍五入到小数点后几位。value
模板 输出 34.23234
{{ value|floatformat:3 }}
34.232
34.00000
{{ value|floatformat:3 }}
34.000
34.26000
{{ value|floatformat:3 }}
34.260
特别有用的是传递 0(零)作为参数,它将把浮点数舍入到最接近的整数。
value
模板 输出 34.23234
{{ value|floatformat:"0" }}
34
34.00000
{{ value|floatformat:"0" }}
34
39.56000
{{ value|floatformat:"0" }}
40
-
random
从给定列表中随机返回一个项目。
1
{{ value|random }}
如果
value
是列表['a', 'b', 'c', 'd']
,输出可能是"b"
。 -
join
用字符串连接一个列表,就像 Python 的
str.join(list)
一样。1
{{ value|join:" // " }}
如果
value
是列表['a', 'b', 'c']
,输出将是字符串"a // b // c"
。 -
slice
返回列表的一个片段。
1
{{ some_list|slice:":2" }}
如果
some_list
是['a', 'b', 'c']
,输出将是['a', 'b']
。 -
first
返回列表中的第一个项目。
1
{{ value|first }}
如果
value
是列表['a', 'b', 'c']
,则输出为'a'
。 -
last
返回列表中的最后一项。
1
{{ value|last }}
如果
value
是列表['a', 'b', 'c', 'd']
,输出将是字符串"d"
。 -
cut
从给定的字符串中删除参数的所有值。
1
{{ value|cut:" " }}
如果
value
是"String with spaces"
,输出将是"Stringwithspaces"
。 -
date
根据给定的格式设置日期。
1
{{ value|date:"Y/m/d" }}
如果
value
是一个datetime
对象(例如,datetime.datetime.datetime.now()
的结果),输出将是字符串'2022/12/13'
。 -
time
根据给定的格式对时间进行格式化。
1
{{ value|time:"H:i:s" }}
如果
value
相当于datetime.datetime.now()
,输出将是字符串"16:02:49"
。 -
add
将参数添加到值中。
1
{{ value|add:"2" }}
如果
value
是4
,那么输出将是6
。1
{{ first|add:second }}
如果
first
是[1, 2, 3]
并且second
是[4, 5, 6]
,则输出为[1, 2, 3, 4, 5, 6]
。 -
safe
标记一个字符串在输出前不需要进一步的 HTML 转义。当自动转义关闭时,该过滤器没有效果。
-
escape
转义字符串的 HTML。具体来说,它可以进行这些替换。
-
-
标签
-
概述
- 标签是这样的:
{% tag %}
。标签比变量更复杂。有的在输出中创建文本,有的通过执行循环或逻辑来控制流程,有的将外部信息加载到模板中,供以后的变量使用。 - 有些标签要求有开始和结束标签。
- Django 有二十多个内置的模板标签。你可以在 内置标签参考 中阅读所有关于它们的信息。
- 标签是这样的:
-
autoescape
-
for
-
循环浏览数组中的每个项目,使该项目在上下文变量中可用。
1
2
3
4
5<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>你可以通过使用
{% for obj in list reversed %}
来反向循环一个列表。 -
如果你需要访问字典中的项目,这也很有用。
1
2
3{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}请记住,对于点运算符来说,字典键查询优先于方法查询。因此,如果
data
字典中包含一个名为'items'
的键,data.items
将返回data['items']
而不是data.items()
。如果你想在模板中使用这些方法,避免添加像字典方法一样命名的键(items
、values
、keys
等)。在 模板变量的文档 中阅读更多关于点运算符的查找顺序。 -
for 循环设置了一组可以在循环体内直接使用的变量:
变量名 描述 forloop.counter
循环计数器,表示当前循环的索引(从 1
开始)。forloop.counter0
循环计数器,表示当前循环的索引(从 0
开始)。forloop.revcounter
反向循环计数器(以最后一次循环为 1
,反向计数)。forloop.revcounter0
反向循环计数器(以最后一次循环为 0
,反向计数)。forloop.first
当前循环为首个循环时,该变量为 True forloop.last
当前循环为最后一个循环时,该变量为 True forloop.parentloop
在嵌套循环中,指向当前循环的上级循环
-
-
for
…empty
当传递到
for
标签中的数组不存在或为空时,可以使用{% empty %}
标签来指定输出的内容1
2
3
4
5
6
7<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul> -
if
{% if %}
标签会判断给定的变量,当变量为 True 时(比如存在、非空、非布尔值 False),就会输出块内的内容1
2
3
4
5
6
7{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}正如你所看到的,
if
标签可能带有一个或多个{% elif %}
分支,以及一个{% else %}
分支。当{% else %}
之前的所有分支条件都不满足时,{% else %}
分支的内容会被显示出来。所有的分支都是可选的。 -
3.1 版后已移除ifequal
和ifnotequal
1
2
3
4{% ifequal a b %} ... {% endifequal %}
是写
{% if a == b %} ... {% endif %}
的过时方式1
2
3
4{% ifnotequal a b %} ... {% endifnotequal %}
被
{% if a != b %} ... {% endif %}
取代 -
ifchanged
检查一个值是否在循环的最后一次迭代中发生了变化。
-
block
定义一个可以被子模板覆盖的块。更多信息请参见 模板继承。
-
extends
表示该模板扩展了一个父模板。
这个标签有两种使用方式:1
2
3
4
5# (带引号)使用字面值 "base.html" 作为要扩展的父模板的名称。
{% extends "base.html" %}
# 使用 variable 的值。如果变量的值是一个字符串,Django 将使用这个字符串作为父模板的名称。如果变量的值是一个 Template 对象,Django 将使用该对象作为父模板。
{% extends variable %} -
url
返回与给定视图和可选参数相匹配的绝对路径引用(不含域名的 URL)。路径中的任何特殊字符将使用
iri_to_uri()
进行编码。1
{% url "namespace:name" 参数1 …… %}
-
csrf_token
这个标签用于 CSRF 保护,如 跨站点请求伪造 的文档中所述。
1
{% csrf_token %}
-
load
加载一个自定义模板标签集。
1
{% load static %}
-
-
创建
static
目录在工程目录下创建名为
static
的目录作为静态文件的存放位置 -
配置
settings.py
文件1
2STATIC_URL = "static/"
STATICFILES_DIRS = [BASE_DIR / "static"] -
保存静态文件
将你的静态文件保存至项目中名为
static
的目录中。如:static/images/123.gif
-
加载静态文件
1
2
3{% load static %}
<img src="{% static 'images/123.gif' %}" alt=""> -
部署
- 概述
django.contrib.staticfiles
提供了一个便利的管理命令,用于将静态文件收集至独立目录,方便你为它们提供服务。
- 将
STATIC_ROOT
配置成你喜欢的目录,在这个目录提供服务,例如:1
STATIC_ROOT = "/www/wwwroot/example.com/static/"
在
settings.py
文件中添加以上内容 - 运行
collectstatic
管理命令1
python manage.py collectstatic
这将会把静态目录下的所有文件拷贝至
STATIC_ROOT
目录。 - 选一个 Web 服务器为这些文件提供服务。 文档 如何部署静态文件 介绍了静态文件的常见部署策略。
- 概述