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

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

创建一些虚拟数据用于测试:

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'},
]

template/watchlist.html

<!DOCTYPE html>
{% set navigation = [('/', 'Home'), ('/about', 'About')] %}
<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 %}
<h5>{{ user.username }}'s Watchlist ({{ movies|length }}):</h5>
<ul>
    {% for movie in movies %}
        <li>{{ movie.name }} - {{ movie.year }}</li>
    {% endfor %}
</ul>
</body>
</html>

模板语法

利用Jinja2这样的模板引擎,我们可以将一部分的程序逻辑放到模板中去。简单地说,我们可以在模板中使用Python语句和表达式来操作数据的输出。但需要注意的是,Jinja2并不支持所有Python语法。而且出于效率和代码组织等方面的考虑,我们应该适度使用模板,仅把和输出控制有关的逻辑放到模板中。

Jinja2允许你在模板中使用大部分Python对象,比如字符串、列表、字典、元组、整型、浮点型、布尔值。它支持基本的运算符号(+ - * /等)、比较符号(如\=\=、!\=等)、逻辑符号(and、or、not和括号)以及in

is、None和布尔值(True、False)

Jinja2提供了多种控制结构来控制模板的输出,其中for和if是最常用 的两种。在Jinja2里,语句使用{%...%}标识,尤其需要注意的是,在语 句结束的地方,我们必须添加结束标签:

和其他语句一样,你需要在for循环的结尾使用endfor标签声明for语 句的结束。在for循环内,Jinja2提供了多个特殊变量,常用的循环变量 如表3-1所示。

loop.index 当前迭代数(从1开始计数)

loop.index0 当前迭代数(从0开始计数)

loop.revindex 当前反向迭代数(从1开始计数)

loop.revindex0 当前反向迭代数(从0开始计数)

loop.first 如果是第一个元素,则为True

loop.last 如果是最后一个元素,则为True

loop.previtem 上一个迭代的条目

loop.nextitem 下一个迭代的条目

loop.length  序列包含的元素数量


0 Comments latest

No comments.