在模板中,也存在if判断和for循环等控制语句。所有的控制语句都是放在{% %}中间的,并且在控制语句结束后,要加入相应的结束语句。下面对if判断语句和for循环语句分别进行讲解。
Jinja2中的if判断语句和Python中的if判断语句非常类似,可以使用关系运算符>、<、>=、<=、==、!=来进行判断,也可以通过and、or、not来进行逻辑操作。我们首先创建一个视图函数if_statement,代码如下。
@app.route("/if") def if_statement(): age = 18 return render_template("if.xhtml",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所示。
图4-5 模板中使用if判断语句
仔细阅读if.html模板代码可以发现,在if语句结束后,需要添加endif关闭if代码块,这跟Python中的用法是有点不同。
Jinja2中的代码缩进只是为了更加方便阅读,任何缩进都不是必需的。
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.xhtml",books=books)
在for_statement视图函数中,首先创建了一个books变量,books是一个列表,里面存放的是图书信息的字典,然后渲染给for.html模板。接下来在模板文件中循环这个列表,代码如下。
因为在table表格标签中,一个tr标签代表表格中的一行,所以在tr外面加了一个for循环,去循环这个books列表。在tr下面,一个td代表一列,每列从book中获取对应的数据,分别是书名、作者、价格。在浏览器中访问http://127.0.0.1:5000/for,显示结果如图4-6所示。
图4-6 Jinja2 for循环
如果被循环的序列(如以上代码中的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.xhtml",books=books)
此时再在浏览器中访问http://127.0.0.1:5000/for,可以看到页面会显示“无数据”,如图4-7所示。
图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="3" style="text-align: center;">无数据</td> </tr> {% endfor %} </tbody> </table>
通过以上代码可以看到,在thead标签中新增了一个叫作序号的表头,tbody中新增了一个叫作loop.index列,loop.index在每次循环时,会显示当前循环的次数,即代表第几行。在浏览器中访问http://127.0.0.1:5000/for,可以看到如图4-8所示的效果图。
图4-8 带有序号的循环
除loop.index外,Jinja2中的for循环中还提供了如表4-2所示的变量。
表4-2 for循环中的变量
表4-2中的13个变量中,只有loop.cycle和loop.changed是函数,其余都是变量。这里再做两个案例来讲解loop.cycle和loop.changed的用法。
(1)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类。
(2)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循环,读者在使用时尤其要注意这两点。