模板
用 Python 生成 HTML 十分无趣,而且相当繁琐,因为你必须手动对 HTML 做转义来保证应用的安全。为此,Flask 配备了 Jinja2 模板引擎。
你可以使用 render_template() 方法来渲染模板。你需要做的一切就是将模板名和你想作为关键字的参数传入模板的变量。这里有一个展示如何渲染模板的简例:在template_demo.py中定义视图函数index
# coding:utf-8 from flask import Flask, render_template app = Flask(__name__) @app.route('/') @app.route('/<name>') def index(name=None): # 使用render_template()来渲染模板 参数第一个为模板页面,第二个为向模板传入的参数,如果为多个值依次传入 return render_template('index.html', name=name) if __name__ == "__main__": app.run(host='0.0.0.0', port=12345, debug=True)
Flask 会在 templates 文件夹里寻找模板。所以,如果你的应用是个模块,这个文件夹应该与模块同级:
在templates文件夹下创建index.html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>title</title> </head> <body> {% if name %} <h1>Hello {{ name }} </h1> {% else %} <h1>Hello World </h1> {% endif%} </body> </html>
运行templates_Demo.py,在浏览器中访问127.0.0.1::12345/ 和 127.0.0.1:12345/circle
render_template()方法第一个参数就是找到你需要指定的模板,第二个参数就是向模板传入变量,如果是多个变量可以在后面一次传入就可以
render_template('index.html', name=name, age=18 .....) 传入多少都可以
那么问题来了,如果我有一大堆数据,难道真的要一个一个传入吗?那是不是看起来有点瘆人啊,那我们就来传入一个字典看看会是怎样的
def index(name=None): data = { 'name': name, 'age': 18 } return render_template('index.html', data)
显然这还不行的,这里报了一个类型错误,说明不能接受字典类型数据,那么可以利用**将字典拆包的放入就应该可以的
# 将字典拆包的方式传入方法中 return render_template('index.html', **data)
接下来我们再来访问一下
显然这种方式是被接受的。注意这里我们用到的模板没有更改,使用的都是上面的模板,所以没有重新给出
字典当中如果包含了一个字典或者列表我们的模板中应该如何接收呢?
def index(name=None): data = { 'name': name, 'age': 18, 'my_dict': {'city': 'harbin'}, 'my_li': [1, 2, 3, 4, 5], } return render_template('index.html', **data)
模板代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>title</title> </head> <body> {% if name %} {# {{ 写入传入的变量名 }} #} <h1>Hello {{ name }} </h1> <hr> <h1>age {{ age }} </h1> <hr> {# 第一种获取字典的方式 #} <h1>my_dict {{ my_dict['city'] }} </h1> <hr> {# 第二种获取字典的方式 #} <h1>my_dict {{ my_dict.city }} </h1> <hr> {# 获取列表的方式 #} <h1>my_li {{ my_li }} </h1> <hr> {# 遍历列表 #} {% for li in my_li %} <h1>my_li {{ li }} </h1> {% endfor %} <hr> {# 获取列表中的单个值,这里获取的是第一个元素 #} <h1>my_li {{ my_li[0] }} </h1> <hr> {% else %} <h1>Hello World </h1> {% endif%} </body> </html>
访问结果
当然模板变量也是支持变量相加的
<h1>my_li[0] + my_li[1] = {{ my_li[0] + my_li[1] }} </h1> <h1>{{ "hello" + "worlds" }} </h1>
过滤器
safe:禁用转义
<p>{{ '<em>hello</em>' | safe }}</p>
capitalize:把变量值的首字母转成大写,其余字母转小写;
<p>{{ 'hello' | capitalize }}</p>
lower:把值转成小写;
<p>{{ 'HELLO' | lower }}</p>
upper:把值转成大写;
<p>{{ 'hello' | upper }}</p>
title:把值中的每个单词的首字母都转成大写;
<p>{{ 'hello' | title }}</p>
trim:把值的首尾空格去掉;
<p>{{ ' hello world ' | trim }}</p>
reverse:字符串反转;
<p>{{ 'olleh' | reverse }}</p>
format:格式化输出;
<p>{{ 'name = %s , age = %d' | format('name',17) }}</p>
striptags:渲染之前把值中所有的HTML标签都删掉;
<p>{{ '<em>hello</em>' | striptags }}</p>
这里就不一一展示了。需要哪个拿去用就好,但是有意思的一点是,过滤器可以连续使用。但是不限定为2个
<p>{{ “ hello world “ | trim | upper }}</p>
列表过滤器
first:取第一个元素
<p>{{ [1,2,3,4,5,6] | first }}</p>
last:取最后一个元素
<p>{{ [1,2,3,4,5,6] | last }}</p>
length:获取列表长度
<p>{{ [1,2,3,4,5,6] | length }}</p>
sum:列表求和
<p>{{ [1,2,3,4,5,6] | sum }}</p>
sort:列表排序
<p>{{ [6,2,3,1,5,4] | sort }}</p>
上面给出的过滤器当然会有不满足自己使用的时候,既然有需求就会有自己动手来定义过滤器的愿望,那么我们来实现它
自定义一个过滤列表的过滤器,需求过滤列表步长为2,也就是间隔一个取一个值,定义流程,首先定义一个自定义过滤器函数,然后将自定义过滤器注册,注册的同时指定是那个过滤器,和过滤器的名字
1 # coding:utf-8 2 3 from flask import Flask, render_template 4 5 app = Flask(__name__) 6 7 8 @app.route('/') 9 @app.route('/<name>') 10 def index(name=None): 11 data = { 12 'name': name, 13 'age': 18, 14 'my_dict': {'city': 'harbin'}, 15 'my_li': [1, 2, 3, 4, 5], 16 } 17 return render_template('index.html', **data) 18 19 20 def list_step_2(li): 21 """自定义过滤器""" 22 return li[::2] 23 24 25 # 注册过滤器 26 app.add_template_filter(list_step_2, 'li2') 27 28 29 if __name__ == "__main__": 30 app.run(host='0.0.0.0', port=12345, debug=True)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>title</title> 6 </head> 7 <body> 8 <h1>过滤my_li = {{ my_li | li2 }}</h1> 9 </body> 10 </html>
展示结果
备注: add_template_filter() 第一个参数是指定的函数名,第二个参数是定义的过滤器名字
另一种自定义过滤器的方式,这里我们定义一个只返回列表第一个元素的过滤器,定义流程,首先定义一个过滤器函数,然后已装饰器的方式注册过滤器,使用template_filter()参数写上过滤器的名字
1 # coding:utf-8 2 3 from flask import Flask, render_template 4 5 app = Flask(__name__) 6 7 8 @app.route('/') 9 @app.route('/<name>') 10 def index(name=None): 11 data = { 12 'name': name, 13 'age': 18, 14 'my_dict': {'city': 'harbin'}, 15 'my_li': [1, 2, 3, 4, 5], 16 } 17 return render_template('index.html', **data) 18 19 20 # 第一种方式添加过滤器 21 def list_step_2(li): 22 """自定义过滤器""" 23 return li[::2] 24 25 26 # 第二种凡是添加过滤器 27 @app.template_filter("fir") 28 def list_first_element(li): 29 return li[0] 30 31 32 # 注册过滤器 33 app.add_template_filter(list_step_2, 'li2') 34 35 36 if __name__ == "__main__": 37 app.run(host='0.0.0.0', port=12345, debug=True)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>title</title> 6 </head> 7 <body> 8 <h1>第1种添加过滤器方式 过滤my_li = {{ my_li | li2 }}</h1> 9 <h1>第2种添加过滤器方式 过滤my_li = {{ my_li | fir }}</h1> 10 </body> 11 </html>
展示效果