使用 Jinja2 模板引擎

    其中,name 是一个变量名,我们用 包裹它表示它是一个变量。我们给 name 传不同的值,模板会返回不同的字符串。像这样,使用真实的值替换变量,再返回最终得到的响应字符串,这一过程称为渲染模板引擎就是渲染模板的程序。

    Flask 默认使用 Jinja2 模板引擎。

    先来看一个简单的程序。

    1. $ cat hello.py
    2. from flask import Flask
    3. app = Flask(__name__)
    4. @app.route("/<name>")
    5. def hello(name):
    6. if name == 'ethan':
    7. return "<h1>Hello, world!</h1> <h2>Hello, %s!</h2>" % name
    8. else:
    9. return "<h1>Hello, world!</h1> <h2>Hello, world!</h2>"
    10. app.run()

    在终端运行上面的代码 python hello.py,终端输出:

    1. * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

    我们在浏览器地址栏输入 http://127.0.0.1:5000/ethan,显示如下:

    在上面的代码中,我们将业务逻辑和表现逻辑混杂在一起了,代码很不优雅,而且当代码变多了后,程序将会变得难以理解和维护。因此,良好的做法应该是将业务逻辑和表现逻辑分开,模板引擎正好可以满足这种需求。

    我们将上面的例子用 Jinja 模板进行改写。默认情况下,Flask 在程序文件夹中的 templates 子文件夹中寻找模板。改写后的文件结构如下:

    1. .
    2. └── templates
    3. └── index.html

    hello.py 文件内容如下:

    index.html 文件内容如下:

    1. <h1>Hello, world!</h1> <h2>Hello, {{ name }}!</h2>

    hello.py 中,我们使用了Flask 提供的 render_template 函数,该函数把 Jinja2 模板引擎集成到了程序中。render_template 函数的第一个参数是模板的文件名。随后的参数都是键值对,表示模板中变量对应的真实值。

    Jinja 模板使用 {{ 变量名 }} 表示一个变量,比如上面的 {{ name }},它告诉模板引擎这个位置的值从渲染模板时使用的数据中获取。

    1. <p> Hello, {{ mydict['key'] }}. Hello, {{ mylist[0] }}. </p>

    Jinja 提供了多种控制结构,来改变模板的渲染流程,比如常见的判断结构,循环结构。示例如下:

    1. {% if user == 'ethan' or user =='peter' %}
    2. <p> Hello, {{ user }} </p>
    3. {% else %}
    4. <p> Hello, world! </p>
    5. {% endif %}
    6. <ul>
    7. {% for user in user_list %}
    8. <li> {{ user }} </li>
    9. {% endfor %}
    10. </ul>

    当有一段代码我们经常要用到的时候,我们往往会写一个函数,在 Jinja 中,我们可以使用宏来实现。例如:

    为了重复使用宏,我们将其保存在单独的文件中,比如 ‘macros.html’,然后在需要使用的模板中导入:

    1. {% import 'macros.html' as macros %}
    2. {{ macros.render_user(user) }}

    另一种重复使用代码的强大方式是模板继承,就像类继承需要有一个基类一样,我们需要一个基模板。比如,我们可以创建一个名为 base.html 的基模板:

    1. <html>
    2. <head>
    3. {% block head %}
    4. <title>{% block title %}{% endblock %} - My Application</title>
    5. {% endblock %}
    6. </head>
    7. <body>
    8. {% block body %}
    9. {% endblock %}
    10. </body>
    11. </html>

    我们可以看到上面的基模板含有三个 block 块:head、title 和 body。下面,我们通过这个基模板来派生新的模板:

    1. {% extends "base.html" %}
    2. {% block title %}Index{% endblock %}
    3. {% block head %}
    4. {{ super() }}
    5. {% endblock %}
    6. {% block body %}
    7. <h1>Hello, World!</h1>

    注意到上面第一行代码使用了 extends 命令,表明该模板继承自 base.html。接着,我们重新定义了 title、head 和 body。另外,我们还使用了 super() 获取基模板原来的内容。