控制语句
在模板中,也存在 if 判断和 for 循环等控制语句。所有的控制语句都是放在 {% %}
中间的,并且在控制语句结束后,要加入相应的结束语句。下面对 if 判断语句和 for 循环语句分别进行讲解。
if判断语句
Jinja2 中的 if 判断语句和 Python 中的 if 判断语句非常类似,可以使用关系运算符 >、<、>=、<=
、==、!= 来进行判断,也可以通过 and、or、not 来进行逻辑操作。我们首先创建一个视图函数 if_statement,代码如下。
@app.route("/if")
def if_statement():
age = 18
return render_template("if.html", age=age)
以上代码定义了一个 age 变量,并且把这个 age 传给了 if.html 模板。在 if.html 模板中,可以根据 age 的大小判断是否成年。if.html 模板的代码如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>if语句</title>
</head>
<body>
{% if age > 18 %}
<div>您已成年!</div>
{% elif age < 18 %}
<div>您未成年!</div>
{% else %}
<div>您刚成年!</div>
{% endif %}
</body>
</html>
因为在视图函数中给 age 赋值为 18,所以在模板中会匹配到以下代码。
<div>您刚成年!</div>
在浏览器中访问 http://127.0.0.1:5000/if ,也可以看到显示的是 “您刚成年!”,如图 4-5 所示。

仔细阅读 if.html 模板代码可以发现,在 if 语句结束后,需要添加 endif 关闭 if 代码块,这跟 Python 中的用法是有点不同。
Jinja2 中的代码缩进只是为了更加方便阅读,任何缩进都不是必需的。 |
for循环语句
Jinja2 中的 for 循环与 Python 中的 for 循环也非常类似,Jinja2 中的 for 循环只是比 Python 中的 for 循环多了一个 endfor 代码块。我们先来实现一下视图函数 for_statement,代码如下。
@app.route("/for")
def for_statement():
books = [
{
"name": "三国演义",
"author": "罗贯中",
"price": 100
},
{
"name": "水浒传",
"author": "施耐庵",
"price": 99
},
{
"name": "红楼梦",
"author": "曹雪芹",
"price": 101
},
{
"name": "西游记",
"author": "吴承恩",
"price": 102
}
]
return render_template("for.html", books=books)
在 for_statement 视图函数中,首先创建了一个 books 变量,books 是一个列表,里面存放的是图书信息的字典,然后渲染给 for.html 模板。接下来在模板文件中循环这个列表,代码如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>for 循环</title>
</head>
<body>
<table>
<thead>
<tr>
<th>书名</th>
<th>作者</th>
<th>价格</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
因为在 table 表格标签中,一个 tr 标签代表表格中的一行,所以在 tr 外面加了一个 for 循环,去循环这个 books 列表。在 tr 下面,一个 td 代表一列,每列从 book 中获取对应的数据,分别是书名、作者、价格。在浏览器中访问 http://127.0.0.1:5000/for ,显示结果如图 4-6 所示。

如果被循环的序列(如以上代码中的 books)中没有元素,那么可以使用 else 来处理。通常我们在浏览网页时,如果某个网页没有数据,则会显示 “无数据”。我们在以上代码中的 for.html 模板加上 else,来实现一个类似的需求,代码如下。
...
{% for book in books %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% else %}
<tr>
<td colspan="3" style="text-align: center;">无数据</td>
</tr>
{% endfor %}
...
在 books 中无数据的情况下,会执行到 else 中,可以将 for_statement 视图函数的 books 修改为一个空的列表,代码如下。
@app.route("/for")
def for_statement():
books = []
return render_template("for.html", books=books)
此时再在浏览器中访问 http://127.0.0.1:5000/for ,可以看到页面会显示 “无数据”,如图 4-7 所示。

Jinja2 中的 for 循环中还内置了许多好用的变量。如要获取当前循环到第几次了,可以通过 loop.index 来实现。我们还是以 for_statement 视图函数为例,首先将 books 变量恢复成以下形式。
books = [
{
"name": "三国演义",
"author": "罗贯中",
"price": 100
},
{
"name": "水浒传",
"author": "施耐庵",
"price": 99
},
{
"name": "红楼梦",
"author": "曹雪芹",
"price": 101
},
{
"name": "西游记",
"author": "吴承恩",
"price": 102
}
]
然后在 for.html 模板中给图书表格新增一个名为序号的列,用 loop.index 来显示每行的序号,修改后的 for.html 模板中的 table 代码如下。
<table>
<thead>
<tr>
<th>序号</th>
<th>书名</th>
<th>作者</th>
<th>价格</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% else %}
<tr>
<td colspan="4" style="text-align: center;">无数据</td>
</tr>
{% endfor %}
</tbody>
</table>
通过以上代码可以看到,在 thead 标签中新增了一个叫作序号的表头,tbody 中新增了一个叫作 loop.index 列,loop.index 在每次循环时,会显示当前循环的次数,即代表第几行。在浏览器中访问 http://127.0.0.1:5000/for ,可以看到如图 4-8 所示的效果图。

除 loop.index 外,Jinja2 中的 for 循环中还提供了如表 4-2 所示的变量。

表4-2 中的 13 个变量中,只有 loop.cycle 和 loop.changed 是函数,其余都是变量。这里再做两个案例来讲解 loop.cycle 和 loop.changed 的用法。
-
loop.cycle:假设现在有一个需求,需要针对 table 标签中行号为奇数的 tr 标签添加 odd 类,行号为偶数的 tr 标签添加 even 类,可以通过以下代码实现。
{% for book in books %}
<tr class="{{ loop.cycle('odd', 'even') }}">
<td>{{ loop.index }}</td>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% endfor %}
在循环 books 的过程中,loop.cycle 也会不断地在 odd 和 even 两个变量中循环,从而实现奇数使用 odd 类,偶数使用 even 类。
-
loop.changed:假设现在想要知道当前循环的 book.name 是否和上次循环的一致,可以通过 loop.changed 实现,代码如下。
{% for book in books %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
<td>{{ loop.changed(book.name) }}</td>
</tr>
{% endfor %}
Jinja2 模板的 for 循环不存在 break 和 continue 来中断循环的语句,这一点是和 Python 中的 for 循环最大的区别,另外 Jinja2 中只有 for 循环,不存在 while 循环,读者在使用时尤其要注意这两点。