渲染模板
假设用户在网站中注册了一个新账户。用户在表单中输入电子邮件地址和密码,然后点击提交按钮。 服务器 接收到包含用户输入数据的请求,然后 Flask 把请求分发到处理注册请求的视图函数。 这个视图函数需要 访问数据库,添加新用户,然后生成响应回送浏览器。这两个过程分别称为业务逻辑和表现逻辑。 把业务逻辑和表现逻辑混在一起会导致代码难以理解和维护。用 Python 生成 HTML 也十分无趣,而且相当 繁琐,因为你必须手动对 HTML 做转义来保证应用的安全。
假设要为一个大型表格构建HTML代码,表格中的数据由数据库中读取的数据以及必要的 HTML 字符串连接在一起。把表现逻辑移到模板中能够提升程序的可维护性。
模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才能 知道。使用真实值替换变量,再返回最终得到的响应字符串,这一过程称为渲染。可以使用 render_template() 方法来渲染模板。你需要做的一切就是将模板名和你想作为关键字的参数传入模板的变 量。
Flask 会在 templates 文件夹里寻找模板。所以,如果你的应用是个模块,这个文件夹应该与模块同级;如 果它是一个包,那么这个文件夹作为包的子目录:
情况 1: 模块:
/application.py
/templates
/hello.html
情况 2: 包:
/application
/__init__.py
/templates
/hello.html
例如:
【hello.html】
<h1>Hello World!</h1>
from flask import render_template
@app.route('/hellotemplate/')
def hellotemplate():
return render_template('hello.html')
Flask使用了一个名为 Jinja2 的强大模板引擎
- {% ... %} Jinja语句,例如判断、循环语句
- {{ ... }} 变量,会显示在浏览器中
- {# ... #} 注释,不会输出到浏览器中
变量规则
在模板中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符,告诉模板引擎这个位置的值从渲染模板时使用的数据中获取。
Jinja2 能识别所有类型的变量, 甚至是一些复杂的类型,例如列表、字典和对象。在模板中使用变量的一 些示例如下:
【helloname.html】
<h1>Hello, {{ name }}!</h1>
@app.route('/hellotemplate/<name>')
def helloname(name):
return render_template('helloname.html',name = name)
可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述模板以首字母大写 形式显示变量 name 的值:
Hello, {{ name|capitalize }}
Jinja2变量过滤器
变量 | 定义 |
---|---|
safe | 渲染值时不转义 |
capitalize | 把值的首字母转换成大写,其他字母转换成小写 |
lower | 把值转换成小写形式 |
upper | 把值转换成大写形式 |
title | 把值中每个单词的首字母都转换成大写 |
trim | 把值的首尾空格去掉 |
striptags | 渲染之前把值中所有的 HTML 标签都删掉 |
控制结构
Jinja2 提供了多种控制结构,可用来改变模板的渲染流程。
- 条件控制语句
【if.html】
{% if name %}
hello, {{name}}
{% else %}
hello, world!
{% endif %}
{% if user %}
Hello, {{ user }}!
{% else %}
Hello, Stranger!
{% endif %}
- for 循环
【for.html】
<ol>
{% for a in range(10) %}
<li>a</li>
{% endfor %}
</ol>
@app.route('/for/')
def fortemplate():
return render_template('for.html')
-
宏(macro)
Jinja2 还支持宏(macro)。宏类似于 Python 代码中的函数(def)。例如: 【macro.html】
{% macro myprint(A) %}
this is {{ A }}
{% endmacro %}
{{ myprint(A) }}
@app.route('/macro/<a>')
def macrotamplate(a):
return render_template('macro.html',A = a)
为了重复使用宏,我们可以将其保存在单独的文件中,然后在需要使用的模板中导入:
【macro2.html】
{% from 'macro.html' import myprint %}
{{ myprint(A) }}
@app.route('/macro2/<a>')
def macro2template(a):
return render_template('macro2.html',A = a)
- 包含(include)
需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中, 以 避免重复:
【include.html】
{% include 'macro.html' %}
@app.route('/include/<a>')
def includetemplate(a):
return render_template('include.html',A = a)
【注意】包含进来的文件里的所有变量也包含进来了,需要在视图函数中指定