Flask 可以在视图函数中返回模板文件,模板引擎默认使用的是 Jinja2 。
通常,返回的 Jinja2 模板文件并不是一个静态的页面,而是同时有静态部分和动态部分。
静态部分可以硬编码写死,动态部分需要通过变量传值或过滤器处理等方式来实现。
一、向 Jinja2 模板文件中传入变量
在 Flask 的视图函数中,将变量的值传递给模板文件。传递的数据类型可以是数字,字符串,列表,字典等所有 Python 中的数据类型。
接下来,使用代码来实现变量的传递。
1. 项目准备工作
继续使用我之前创建的 FlaskProject 虚拟环境,项目文件名也叫 FlaskProject ,在 FlaskProject 目录下创建好了一个叫 templates 的模板文件夹,用于存放模板文件。
参考:Flask 中的Jinja2模板引擎
2. 实现视图函数
在项目文件夹 FlaskProject 下创建一个 flask_jinja2.py 文件,在里面定义需要传递的变量数据和视图函数。
代码语言:javascript复制from flask import Flask, render_template
app = Flask(__name__)
@app.route('/args')
def temp_jinja2():
data = {
'Python': '编程语言',
'Flask': 'Web 框架',
'Jinja2': '模板引擎',
'HTML': '前端语言'
}
return render_template('route_two.html', data=data)
if __name__ == '__main__':
app.run(debug=True)
在上面的代码中,视图函数对应的路由是 /args ,视图函数中定义了一个字典数据 data ,这里只以字典作为例子,其他的数据类型一样。
在 rander_template 函数中,返回的模板文件是 route_two.html ,按照关键字参数的方式将数据传递给 route_two.html 。等号右边的 data 就是视图函数中定义的字典 data ,等号左边的 data 是在 route_two.html 中获取数据时使用的变量名。
在最后的 app.run() 中指定 debug=True ,当代码发生变化时,不需要重新运行 Flask APP ,方便我们慢慢的调试。
3. 在模板文件中获取和使用变量
在模板文件夹 templates 中创建模板文件 route_two.html ,然后编写模板,解析后端传入的 data 数据。
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Jinja2 Args</title>
</head>
<body>
<h2 style="color: red">获取 data 中的数据:</h2>
<p style="color: blue"> {{ data['Python'] }} </p>
<p style="color: blue"> {{ data['Flask'] }} </p>
<p style="color: blue"> {{ data.Jinja2 }} </p>
<p style="color: blue"> {{ data.HTML }} </p>
<br/>
{% if data %}
{{ data.keys() }}
{% else %}
<p style="color: blue"> Hello Jinja2 ! </p>
{% endif %}
<br/>
<br/>
{% for key in data.keys() %}
<div>
<p style="color: rebeccapurple"> {{ key }} : {{ data[key] }} </p>
</div>
{% endfor %}
</body>
</html>
后端视图函数中传入模板文件的数据 data 是一个字典,前端接收数据的变量也是 data ,保持前后端的变量名相同,对于数据比较多的情况是比较好的,避免弄混了。
在模板文件中,使用变量的语法是双大括号 {{ }} ,将变量写在两个大括号中间,这种语法在前端叫做“胡子语法”。
获取字典中的值有两种方法,一种是 Python 中字典的使用方式 data['key'],一种是通过对象属性的方式 data.key。获取字典中的键的方法与 Python 中的方法相同 data.keys() ,不过这种方式获取到的是一个迭代器对象,要一个一个的取出需要使用遍历。
在模板语言中也可以使用 if...else... 或 for 循环来编写 if 代码块或 for 循环代码块。
运行后端 Flask APP 服务器,对应的路由是 /args,/args 路由对应的视图函数是 temp_jinja2() ,temp_jinja2() 中给模板文件传递了字典 data ,最后返回模板文件 route_two.html 。
用浏览器访问 http://127.0.0.1:5000/args 或 http://localhost:5000/args ,页面效果如下:
二、Jinja2 模板文件中的过滤器
有时候我们不仅仅需要显示变量的值,我们还需要对变量做一些格式化、运算等处理。
而在模板中不能直接调用 Python 中的函数和方法,这就需要使用过滤器。
过滤器的本质是函数,过滤器中封装了对变量的处理,可以直接调用过滤器的函数名来使用过滤器。
过滤器的使用方式为:变量名 | 过滤器(参数)。大部分过滤器没有参数,如果有参数的话传入参数即可。如果是没有任何参数的过滤器,可以把括号省略掉。
1. 实现视图函数
继续使用上面的实现的视图函数,只是把返回的模板文件换成 route_three.html 。
视图函数相同,传给模板文件的数据也相同,变化的只是 route_three.html 中对数据的处理方式。
2. 在模板文件中获取变量和使用过滤器
在模板文件夹 templates 中创建模板文件 route_three.html ,然后编写模板,使用过滤器处理视图函数传递过来的数据 data 。
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Jinja2 Filter</title>
</head>
<body>
<h2 style="color: red">过滤器处理 data 中的数据:</h2>
<p style="color: blue"> {{ 'Hello Jinja2 !' | reverse }} </p>
<br/><p style="color: blue"> {{ data.keys() | upper }} </p>
<br/>
{% for key in data.keys() %}
<div>
<p style="color: rebeccapurple"> {{ '%s : %s' | format(key, data[key]) }} </p>
</div>
{% endfor %}
<br/><p style="color: blue"> {{ data.keys() | first | upper }} </p>
{% filter upper %}
python 碎片<br/>
{{ data }}
{% endfilter %}
</body>
</html>
Jinja2 已经实现了很多常用的过滤器,可以直接调用。
reverse 可以将一个字符串进行翻转,upper 可以将字符串全部转换成大写。
过滤器可以嵌套在 if 代码块或 for 代码块中使用,format() 类似于 Python 中的字符串格式化 format() 方法,用于字符串的拼接。
多个过滤器可以进行链式调用,如果需要,可以在后面无限增加。Jinja2 会依次执行每一个过滤器,展示最终的结果。
也可以使用 {% filter 过滤器名 %} ... {% endfilter %} 来对一整段数据进行过滤处理。
用浏览器访问 http://127.0.0.1:5000/args 或 http://localhost:5000/args ,页面效果如下:
三、Jinja2 中常见的内置过滤器
Jinja2 中内置了很多过滤器,可以很方便的使用。常见的内置过滤器如下:
1. safe:禁用字符转义。
如果字符串中有 HTML 标签等特殊的字符,使用 safe 不会进行转义,HTML 标签才会被浏览器解析生效。
2. capitalize:把变量值的首字母转换成大写,其余字母转换成小写。
3. lower:把变量值全部转换成小写。
4. upper:把变量值全部转换成大写。
5. title:把变量值中的每个单词的首字母都转换成大写。
6. reverse:字符串反转。
7. format():字符串格式化输出。
8. striptags:页面渲染之前把变量值中所有的 HTML 标签都删掉。
9. truncate: 字符串截取。
10. first:取列表或迭代器中的第一个元素。
11. last:取列表或迭代器中的最后一个元素。
12. length:返回列表的长度。
13. sum:对数字列表求和。
14. sort:对列表排序。
一般来说,Jinja2 内置的过滤器已经能满足我们常用的需求了。如果内置的过滤器都不满足使用的场景,也可以自定义过滤器,这里就不继续介绍了。