模版是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体指只在请求的上下文中才能知道。使用真实值替换变量,再返回最终得到的响应字符串,这一过程称为 渲染 。为了渲染模版, Flask 使用了一个名为 Jinja2 的强大模版引擎。
形式最简单的Jinja2模版就是一个包含响应文本的文件。
示例 1 templates/index.html
<h1>Hello World!</h1>示例 2 templates/user.html
<h1>Hello, {{ name }}!</h1>示例2 中包含一个使用变量表示的动态部分 {{ name }}
默认情况下, Flask 在程序文件夹中的 templates 子文件夹中寻找模版。我们将 示例1 和 示例2 分别命名为 index.html 和 user.html 存放在 templates 文件夹下。
视图函数对应为:
from flask import Flask, render_template #... @app.route('/') def index(): return render_template('index.html') @app.route('/user/<name>') def user(name): return render_template('user.html', name=name)Flask 提供的 render_template 函数把 Jinja2 模版引擎集成到程序中。 render_template 函数的第一个参数是模版的文件名。随后的参数都是键值对, 表示模版中变量对应的真实值。在这段代码中,第二个模版收到一个名为 name 的变量。
视图函数中 name=name 是关键字参数,左边的 name 表示参数名,就是模版中的占位符;右边的 name 是当前作用域中的变量,表示同名参数的值。
示例2 在模版中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符, 告诉模版引擎这个位置的值从渲染模版时使用的数据中获取。
Jinja2 能识别所有类型的变量,甚至 列表、字典和对象。在模版中使用变量的一些示例如下:
<p>A vakue from a dictionary: {{ mydict['key'] }}.</p> <p>A vakue from a list: {{ mylist[3] }}.</p> <p>A vakue from a list, with a variable index: {{ mylist[myintvar] }}.</p> <p>A vakue from a object's method: {{ myobj.somemethod() }}.</p>可以使用 过滤器 修改变量, 过滤器名添加在变量名之后, 中间使用竖线分隔。例如,下述模版以首字母大写形式显示变量 name 值:
Hello, {{ name|capitalize }}常用过滤器:
过滤器名说明safe渲染值时不转义capitalize把值的首字母转换成大写,其他字母转换成小写lower把值转换成小写形式upper把值转换成大写形式title把值中的每个单词的首字母都转成大写trim把值的首尾空格去掉scriptags渲染之前把值中所有的 HTML 标签都删掉注意:千万别在不可信的值上使用 safe 过滤器,例如用户在表单中输入的文本。 默认情况下,出于安全考虑, Jinja2 会转移所有变量。例如, 如果一个变量的值为 '<h1>Hello</h1>' ,Jinja2 会将其渲染成 '<h1>Hello</h1>',浏览器能显示 h1 元素,但不会进行解释。
Jinja2 提供了多种控制结构,可用来改变模版的渲染流程。
宏类似 python 中的函数
{% macro render_comment(comment) %} <li>{{ comment }}</li> {% endmacro %} <ul> {% for comment in comments %} {{ render_comment(comment) }} {% endfor %} </ul>需要在多出重复使用的模版代码片段可以写入单独的文件,再包含在所有模块中,以避免重复:
{% include 'common.html' %}另一种重复使用代码的强大方式是模版集成,它类似与 Python 代码中的类继承。首先, 创建一个名为 base.html 的基模版:
<html> <head> {% block head %} <title>{% block title%}{% endblock %} - My Application<title> {% endblock %} </head> <body> {% block body %} {% endblock %} </body> </head>block 标签定义的元素可在衍生模版中修改。在 base.html 中,我们定义了名为 head、title 和 body 的块。注意, title 包含在 head 中。 下面这个示例是基模版的衍生模版:
{% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %} {{ supper() }} <style> </style> {% endblock %} {% block body %} <h1>Hello, World!</h1> {% endblock %}extends 指令声明这个模版衍生自 base.html。在 extends 指令后, 基模版中的 3 个块被重新定义, 模版引擎会将其插入适当的位置。注意新定义的 head 块, 在基模版中其内容不是空的, 所以使用 super() 获取原来的内容。
