Skip to content

模板

前面,当用户访问程序的根地址时,我们的视图函数会向客户端返回一行 HTML 代码。然而,一个完整的 HTML 页面往往需要几十行甚至上百行代码,如果都写到视图函数里,那可真是个噩梦。这样的代码既不简洁也难于维护,正确的做法是把 HTML 代码存储在单独的文件中,以便让程序的业务逻辑和表现逻辑分离,即控制器和用户界面的分离

在动态 Web 程序中,视图函数返回的 HTML 数据往往需要根据相应的变量(比如查询参数)动态生成。当 HTML 代码保存到单独的文件中时,我们没法再使用字符串格式化或拼接字符串的方式来在 HTML 代码中插入变量,这时我们需要使用模板引擎(template engine)。借助模板引擎,我们可以在 HTML 文件中使用特殊的语法来标记出变量,这类包含固定内容和动态部分的可重用文件称为模板(template)

模板引擎的作用就是读取并执行模板中的特殊语法标记,并根据传入的数据将变量替换为实际值,输出最终的 HTML 页面,这个过程称为渲染(rendering)。Flask 默认使用的模板引擎是 Jinja2,它是一个功能齐全的 Python 模板引擎,除了设置变量,还允许我们在模板中添加 if 判断,执行 for 迭代,调用函数等,以各种方式控制模板的输出对于 Jinja2 来说,模板可以是任何格式的纯文本文件,比如 HTML、XML、CSV、LaTeX 等。

模板基本用法

创建模板

假设我们需要编写一个用户的电影清单页面,类似 IMDb 的 watchlist 页面的简易版,模板中要显示用户信息以及用户收藏的电影列表,包含电影的名字和年份。我们首先创建一些虚拟数据用于测试显示效果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
user = {
    'username': 'Grey Li',
    'bio': 'A boy who loves movies and music.',
}

movies = [
    {'name': 'My Neighbor Totoro', 'year': '1988'},
    {'name': 'Three Colours trilogy', 'year': '1993'},
    {'name': 'Forrest Gump', 'year': '1994'},
    {'name': 'Perfect Blue', 'year': '1997'},
    {'name': 'The Matrix', 'year': '1999'},
    {'name': 'Memento', 'year': '2000'},
    {'name': 'The Bucket list', 'year': '2007'},
    {'name': 'Black Swan', 'year': '2010'},
    {'name': 'Gone Girl', 'year': '2014'},
    {'name': 'CoCo', 'year': '2017'},
]

我们在 templates 目录下创建一个 watchlist.html 作为模板文件,然后使用 Jinja2 支持的语法在模板中操作这些变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>{{ user.username }}'s Watchlist</title>
</head>
<body>
<a href="{{ url_for('index') }}">&larr; Return</a>
<h2>{{ user.username }}</h2>
{% if user.bio %}
    <i>{{ user.bio }}</i>
{% else %}
    <i>This user has not provided a bio.</i>
{% endif %}
{# Below is the movie list (this is comment) #}
<h5>{{ user.username }}'s Watchlist ({{ movies|length }}):</h5>
<ul>
    {% for movie in movies %}
    <li>{{ movie.name }} - {{ movie.year }}</li>
    {% endfor %}
</ul>
</body>
</html>

在模板中添加 Python 语句和表达式时,我们需要使用特定的定界符把它们标示出来。

可以在上面的代码中看到 Jinja2 里常见的三种定界符