表单 flask-wtf 的使用
1.跨站请求伪造保护
Flask-WTF 能保护所有表单免受跨站请求伪造(Cross-Site Request Forgery,CSRF)的攻击。
为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF 使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。设置密钥的方法如示例 4-1 所示。
# 如果要用flask_wtf模块, SECRET_KEY就必须设置
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config 字典可用来存储框架、扩展和程序本身的配置变量。使用标准的字典句法就能把配置值添加到 app.config 对象中。这个对象还提供了一些方法,可以从文件或环境中导入配置值。
SECRET_KEY 配置变量是通用密钥,可在 Flask 和多个第三方扩展中使用。如其名所示,加密的强度取决于变量值的机密程度。不同的程序要使用不同的密钥,而且要保证其他人不知道你所用的字符串
2.表单类
使用 Flask-WTF 时,每个 Web 表单都由一个继承自 Form 的类表示。这个类定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数。验证函数用来验证用户提交的输入值是否符合要求。
from flask.ext.wtf import Form
# 导入表单类
from wtforms import StringField, SubmitField
# 导入表单验证类
from wtforms.validators import Required
class NameForm(Form):
name = StringField('What is your name?', validators=[Required()])
submit = SubmitField('Submit')
'what is your name? ' 是label validators中是表单验证类,表单验证类放在列表中
# 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验证函数
Email 验证电子邮件地址
EqualTo 比较两个字段的值;常用于要求输入两次密码进行确认的情况
IPAddress 验证 IPv4 网络地址
Length 验证输入字符串的长度
NumberRange 验证输入的值在数字范围内
Optional 无输入值时跳过其他验证函数
Required 确保字段中有数据
Regexp 使用正则表达式验证输入值
URL 验证 URL
AnyOf 确保输入值在可选值列表中
NoneOf 确保输入值不在可选值列表中
3.把表单渲染成HTML
表单字段是可调用的,在模板中调用后会渲染成 HTML。
假设视图函数把一个 NameForm 实例通过参数 form 传入模板,在模板中可以生成一个简单的表单,
简单渲染
<form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name(id='my-text-field') }}
{{ form.submit() }}
</form>
#可以把参数传入渲染字段的函数,传入的参数会被转换成字段的 HTML 属性。例如,可以为字段指定 id 或 class 属性,然后定义 CSS 样式:例如 form.name(id='my-text-field')
Bootstrap 渲染
可以使用 Bootstrap 中预先定义好的表单样式渲染整个 Flask-WTF 表单
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
wtf.quick_form() 函数的参数为 Flask-WTF 表单对象,使用 Bootstrap 的默认样式渲染传入的表单
4.在视图函数中处理表单
视图函数 index() 不仅要渲染表单,还要接收表单中的数据。
@app.route('/', methods=['GET', 'POST'])
def index():
name = None
form = NameForm()
# 对传回的数据进行对比校验
if form.validate_on_submit():
name = form.name.data
# 将form中的数据清空
form.name.data = ''
return render_template('index.html', form=form, name=name)
5.重定向和用户会话
为刷新页面时浏览器会重新发送之前已经发送过的最后一个请求.如果最后一个请求是个post请求, 会导致用户体验不好,使用重定向作为 POST 请求的响应,这个技巧称为 Post/ 重定向 /Get 模式。
from flask import Flask, render_template, session, redirect, url_for
@app.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('index.html', form=form, name=session.get('name'))
# 使用session.get('name') 当没有时,返回none
6 Flash消息
请求完成后,有时需要让用户知道状态发生了变化。这里可以使用确认消息、警告或者错误提醒。
这种功能是 Flask 的核心特性。如示例 4-6 所示,flash() 函数可实现这种效果。
from flask import Flask, render_template, session, redirect, url_for, flash
@app.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
old_name = session.get('name')
# 当用户传回用户名和session中的name不一样时
if old_name is not None and old_name != form.name.data:
#如果两个名字不一样,就会调用 flash() 函数,在发给客户端的下一个响应中显示一个消息。
flash('Looks like you have changed your name!')
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('index.html',form=form, name=session.get('name'))
Flask 把 get_flashed_messages() 函数开放给模板,用来获取并渲染消息
{% block content %}
<div class="container">
# 使用循环是因为在之前的请求循环中每次调用 flash() 函数时都会生成一个消息
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ message }}
</div>
{% endfor %}
{% block page_content %}{% endblock %}
</div>
{% endblock %}
get_flashed_messages() 函数获取的消息在下次调用时不会再次返回,因此 Flash 消息只显示一次,然后就消失了。