Flask模板
- 使用模板
- 使用方法
- 变量
- 过滤器
- 字符串过滤器
- 列表过滤器
- 自定义过滤器
- 表单
- WTForms支持的HTML标准字段
- WTForms常用的验证函数
- 表单的实际使用
- 控制语句
- if语句
- for语句
- 宏
- 不带参数的宏
- 带参数的宏
- 将宏封装在HTML文件中
- 模板的继承和包含
- 模板继承
- 模板包含
- Flask模板中的特殊变量和方法
- config对象
- request对象
- url_for()方法
- get_flashed_messages()方法
使用模板
使用方法
在Flask中使用render_template
进行模板渲染
from flask import Flask, render_template
@app.route('/index')
def index():
return render_template('index.html', name='lisi', age=18)
注:在Flask中向模板中传递变量时,不能使用字典,而是要使用 变量名=值
的方式;如需使用字典,需要使用 **dict
的方式进行解包
变量
Flask中,在模板中使用变量的方式和Django相同,都是采用 {{ 变量名 }}
的方式
对于字典,可以使用 {{ my_dict['key'] }}
或者 {{ my_dict.key }}
的方式获取值
对于列表,可以使用 {{ my_list[index] }}
的方式获取值
同时,在模板中可以直接进行运算和字符串的拼接
@app.route('/index')
def index():
data = {
'name': 'lisi',
'age': 18,
'my_dict': {'city': 'beijing'},
'my_list': [1, 2, 3, 4, 5],
'my_int': 0
}
return render_template('index.html', **data)
对应的模板内容为:
<p>name = {{ name }}</p> <!-- 直接获取变量 -->
<p>age = {{ age }}</p>
<p>my_dict: city = {{ my_dict }}</p>
<p>my_dict: city = {{ my_dict['city'] }}</p> <!-- 获取字典对应键的值 -->
<p>my_dict: city = {{ my_dict.city }}</p> <!-- 获取字典对应键的值 -->
<p>my_list: {{ my_list }}</p>
<p>my_list[{{ my_int }}]: {{ my_list[my_int] }}</p> <!-- 获取列表对应索引的值 -->
<p>my_list[0] + my_list[1] = {{ my_list[0] + my_list[1] }}</p> <!-- 进行运算 -->
<p>{{ 'hel' + 'lo world' }}</p> <!-- 字符串拼接 -->
过滤器
Flask中的过滤器使用方式如下,同时还支持链式使用:
<p>a{{ ' flask world '|trim }}a</p>
<p>a{{ ' flask world '|trim|upper }}a</p> <!-- 链式使用 -->
字符串过滤器
1> safe:禁用转义
2> capitalize:把变量值的首字母转成大写,其余字母转小写
3> lower:把值转成小写
4> upper:把值转成大写
5> title:把值中的每个单词的首字母都转成大写
6> trim:把值的首尾空格去掉
7> reverse:字符串反转,<p>{{ 'olleh' | reverse }}</p>8> format:格式化输出,<p>{{ '%s is %d' | format('name', 17) }}</p>9> striptags:渲染之前把值中所有的HTML标签都删掉
列表过滤器
1> first:取第一个元素
2> last:取最后一个元素
3> length:获取列表长度
4> sum:列表求和
5> sort:列表排序
自定义过滤器
自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器
- 方法一:使用函数:
app.add_template_filter(过滤器函数名, 模板中使用的过滤器名字)
def list_step_2(li):
return li[::2]
# 注册过滤器,将自定义的过滤器添加到应用中
app.add_template_filter(list_step_2, 'li2')
- 方法二:使用装饰器:
app.template_filter(模板中使用的装饰器名字)
@app.template_filter('li3')
def list_step_3(li):
return li[::3]
- 使用自定义的过滤器
<p>{{ my_list|li2 }}</p>
<p>{{ my_list|li3 }}</p>
表单
在 Flask 中,为了处理表单,一般会使用 Flask-WTF 扩展,它封装了 WTForms,并且它有验证表单数据、快速定义表单模板、进行CSRF
验证的功能
使用Flask-WTF需要配置参数SECRET_KEY
CSRF_ENABLED
是为了CSRF
(跨站请求伪造)保护,SECRET_KEY
用来生成加密令牌,当 CSRF
激活的时候,该设置会根据设置的密匙生成加密令牌
安装:pip install Flask-WTF
WTForms支持的HTML标准字段
字段对象 | 说明 |
StringField | 文本字段 |
TextAreaField | 多行文本字段 |
PasswordField | 密码文本字段 |
HiddenField | 隐藏文本字段 |
DateField | 文本字段,值为datetime.date格式 |
DateTimeField | 文本字段,值为datetime.datetime格式 |
IntegerField | 文本字段,值为整数 |
DecimalField | 文本字段,值为decimal.Decimal |
FloatField | 文本字段,值为浮点数 |
BooleanField | 复选框,值为True和False |
RadioField | 一组单选框 |
SelectField | 下拉列表 |
SelectMultipleField | 下拉列表,可选择多个值 |
FileField | 文本上传字段 |
SubmitField | 表单提交按钮 |
FormField | 把表单作为字段嵌入另一个表单 |
FieldList | 一组指定类型的字段 |
WTForms常用的验证函数
验证函数 | 说明 |
DataRequired | 确保字段中有数据 |
EqualTo | 比较两个字段的值,常用于比较两次密码输入 |
Length | 验证输入的字符串长度 |
NumberRange | 验证输入的值在数字范围内 |
URL | 验证URL |
AnyOf | 验证输入值在可选列表中 |
NoneOf | 验证输入值不在可选列表中 |
表单的实际使用
视图函数如下:
from flask import Flask, render_template, redirect, url_for, session
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, EqualTo
app = Flask(__name__)
# 添加SECRET_KEY
app.config['SECRET_KEY'] = 'aldksf98asd76'
# 定义表单的模型类
class RegisterForm(FlaskForm):
# label:说明文字;validators:验证器,列表
username = StringField(label='用户名', validators=[DataRequired('用户名不能为空')])
password = PasswordField(label='密码', validators=[DataRequired('密码不能为空')])
password2 = PasswordField(label='确认密码', validators=[DataRequired('确认密码不能为空'), EqualTo('password', '两次密码不一致')])
submit = SubmitField(label='提交')
@app.route('/register', methods=['GET', 'POST'])
def register():
# 创建表单模型类的对象,
# 如果是post请求,前端发送的数据,flask会在构造form对象的时候,将数据自动存放到form对象中
form = RegisterForm()
# 判断form中的数据是否合理,数据全部合理则返回True,否则返回False
if form.validate_on_submit():
# 表示验证合格,提取数据
uname = form.username.data
pwd = form.password.data
pwd2 = form.password2.data
print(uname, pwd, pwd2)
session['username'] = uname
return redirect(url_for('index'))
return render_template('register.html', form=form)
@app.route('/index')
def index():
username = session['username']
return 'hello %s' % username
if __name__ == '__main__':
app.run(debug=True)
模板内容如下:
<form method="post">
{{ form.csrf_token }} <!-- 设置csrf_token -->
<p>{{ form.username.label }}:{{ form.username }}</p>
{% for msg in form.username.errors %}
<p>{{ msg }}</p>
{% endfor %}
<p>{{ form.password.label }}:{{ form.password }}</p>
{% for msg in form.password.errors %}
<p>{{ msg }}</p>
{% endfor %}
<p>{{ form.password2.label }}:{{ form.password2 }}</p>
{% for msg in form.password2.errors %}
<p>{{ msg }}</p>
{% endfor %}
{{ form.submit }}
</form>
控制语句
if语句
{% if %}
{% endif %}
for语句
{% for item in samples %}
{% endfor %}
宏
类似于 Python 中的函数,宏的作用就是在模板中重复利用代码,避免代码冗余
不带参数的宏
<!-- 定义宏 -->
{% macro input() %}
<input type="text" value="" size="30">
{% endmacro %}
<!-- 使用宏 -->
{{ input() }}
带参数的宏
<!-- 定义宏 -->
{% macro input2(type, size, value='abc') %}
<input type="{{ type }}" value="{{ value }}" size="{{ size }}">
{% endmacro %}
<!-- 使用宏 -->
{{ input2('password', 50) }}
将宏封装在HTML文件中
创建一个 HTML 文件 macro_input.html
,里面可以只存放宏
{% macro input3(type, size, value='abc') %}
<input type="{{ type }}" value="{{ value }}" size="{{ size }}">
{% endmacro %}
从其他 HTML 文件中导入并使用宏
{% import 'macro_input.html' as m_input %}
{{ m_input.input3('text', 20) }}
模板的继承和包含
模板继承
Flask 中模板的继承和 Django 中是相同的。父模板中可以通过 {% block top %}{% endblock top %}
在模板中预留位置;子模板可以使用 extends
指令调用父模板,同时可以使用 super()
使用父模板中的内容
父模板:base.html
{% block top %}
{% endblock top %}
子模板:
{% extends 'base.html' %}
{% block top %}
需要填充的内容
{% endblock top %}
模板包含
模板包含的作用是将另一个模板整个加载到当前模板中,并直接渲染,使用如下:
{\% include 'hello.html' %}
注:包含在使用时,如果包含的模板文件不存在时,程序会抛出 TemplateNotFound
异常,可以加上 ignore missing
关键字,如果包含的模板文件不存在,会忽略这条 include
语句,示例如下:
{\% include 'hello.html' ignore missing %}
Flask模板中的特殊变量和方法
在 Flask 中,有一些特殊的变量和方法是可以在模板文件中直接访问的
config对象
config
对象就是 Flask 的 config
对象,也就是 app.config
对象,可以在模板中直接访问
{{ config.SQLALCHEMY_DATABASE_URI }}
request对象
就是 Flask 中表示当前请求的 request
对象,request
对象中保存了一次 HTTP 请求的一切信息
属性 | 说明 | 类型 |
data | 记录请求体中的数据,并转换为字符串 | * |
form | 记录请求中的表单数据 | MultiDict |
args | 记录请求中的查询参数 | MultiDict |
cookies | 记录请求中的cookie信息 | Dict |
headers | 记录请求中的报文头 | EnvironHeaders |
method | 记录请求使用的HTTP方法 | GET/POST |
url | 记录请求的URL地址 | string |
files | 记录请求上传的文件 | * |
{{ request.url }}
url_for()方法
url_for()
会返回传入的路由函数对应的 URL,所谓路由函数就是被app.route()
路由装饰器装饰的函数。如果定义的路由函数是带有参数的,则可以将这些参数作为命名参数传入
{{ url_for('index') }}
{{ url_for('post', post_id=1024) }}
get_flashed_messages()方法
返回之前在 Flask 中通过 flash()
传入的信息列表。把字符串对象表示的消息加入到一个消息队列中,然后通过调用 get_flashed_messages()
方法取出
{% for message in get_flashed_messages() %}
<p>{{ message }}</p>
{% endfor %}
视图函数内容如下:
from flask import Flask, flash, render_template
app = Flask(__name__)
flag = True
# flash是存储在session中的,所以需要设置SECRET_KEY
app.config['SECRET_KEY'] = 'alkdd9a8s6d9898ad'
@app.route('/')
def index():
global flag
if flag:
flash('hello') # 添加闪现信息
flag = False
return render_template('flash.html')