for循环

1. 简单示例

jinjia2模板里不仅支持if条件语句,还支持for循环, 不过与python不同,在模板里并不支持break和continue,下面的例子里后端服务从数据库里查出若干个学生的信息

stu_lst = [
    {'name': '小明', 'age': 14, 'score': 98},
    {'name': '小刚', 'age': 13, 'score': 95},
    {'name': '小红', 'age': 15, 'score': 96}
]

这些信息需要在前端的table标签中展示
新建stu.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table border="1">

    <tr>
        <th>姓名</th>
        <th>年龄</th>
        <th>分数</th>
    </tr>

    <tbody>
    {% for stu in stu_lst %}
    <tr>
        <td>{{ stu['name'] }}</td>
        <td>{{ stu['age'] }}</td>
        <td>{{ stu['score'] }}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
</body>
</html>

在app.py中新增视图处理函数

@app.route('/stu')
def stu():
    stu_lst = [
        {'name': '小明', 'age': 14, 'score': 98},
        {'name': '小刚', 'age': 13, 'score': 95},
        {'name': '小红', 'age': 15, 'score': 96}
    ]

    return render_template('stu.html', stu_lst=stu_lst)

启动服务,在浏览器里输入http://127.0.0.1:5000/stu

页面展示内容

2. 特殊的变量

在for循环里,你可能需要知道当前循环的一些信息,比如当前循环是第几次循环,再比如可迭代序列里有多少个元素,为此jinjia提供了以下特殊变量

变量 描述
loop.index 当前循环迭代的次数(从 1 开始)
loop.index0 当前循环迭代的次数(从 0 开始)
loop.revindex 到循环结束需要迭代的次数(从 1 开始)
loop.revindex0 到循环结束需要迭代的次数(从 0 开始)
loop.first 如果是第一次迭代,为 True
loop.last 如果是最后一次迭代,为 True
loop.length 序列中的项目数
loop.cycle 在一串序列间期取值的辅助函数

这些特殊变量都比较好理解,只有最后一个cycle需要解释一下

{% for row in rows %}
    <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}

这段for循环控制语句生成多个li标签,我们希望相邻两行的li标签的class是不同的,这样可以让页面更加美观,loop.cycle可以周期性的从序列中取值,这样就可以实现功能了。如果不使用cycle,那么你大概只能根据loop.index的值是否能整除2来决定设置li标签的class属性到底是odd还是even。

3. 递归使用循环

在模板里,我们不能定义函数,因此一些需要递归处理的数据也就不能使用递归函数了,但你可以递归调用循环

<ul class="sitemap">
{%- for item in sitemap recursive %}
    <li><a href="{{ item.href|e }}">{{ item.title }}</a>
    {%- if item.children -%}
        <ul class="submenu">{{ loop(item.children) }}</ul>
    {%- endif %}</li>
{%- endfor %}
</ul>

上面这个例子递归渲染站点地图,在for循环定义的末尾增加了recursive修饰,这表明它可以递归调用,如果item有自己的子节点,那么可以通过loop来启动递归调用,
{{ loop(item.children) }} 与下面的代码是等价的

{%- for item in item.children recursive %}
...
{%- endfor %}

4. 注意事项

与python语法不同,在jinjia模板里,你不能使用break和continue,但你可以过滤一些符合条件的项目

{% for user in users if not user.hidden %}
    <li>{{ user.username|e }}</li>
{% endfor %}

遍历到的user如果hidden属性为True,那么就会跳过这个用户。

在模板里,你同样可以使用for ... else这种形式,如果for循环一次都没有进行,则进入到else

<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% else %}
    <li><em>no users found</em></li>
{% endfor %}
</ul>

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案