处理Web表单的扩展 Flask-WTF
Flask-wtf 对WTForms包进行了包装,方便集成入Flask框架
跨站请求保护
CSRF(Cross-Site Request Forgery)是指恶意网站把请求发送到被攻击者已登录的其他网站就会引发CSRF攻击
为了实现CSRF保护,需要程序设置密钥,生成加密令牌,再用来验证表单数据真伪。非常简单:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
不过在生产环境,不会直接写入程序,而会从文件或环境中导入配置值,Flask-wtf提供了方法来实现
表单类
使用Flask-wtf时,每一个表单都由一个继承自Form类表示,这个类定义表单的字段,每个字段由对象表示,
字段对象可以附属一个或多个验证函数,验证函数负责验证用户提交输入值是否符合要求
示范:
from flask.ext.wtf import Form
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired,Email
class NameForm(Form):
name = StringField('what is your name ?',validators=[DataRequired()])
email = StringField('what is your email ?',validators=[Email()])
submit = SubmitField('Submit')
上面代码定义了3个字段:name,email,submit三个字段,name和email表示"text" 的input元素,
submit表示type = 'submit'的“input”元素。DataRequired接受用户输入之后,确保提交字段不为空,
Email确保输入为符合邮件的函数
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内建验证函数
验证函数 | 说明 |
---|---|
验证邮件地址 | |
EqualTo | 比较2个字段值,一般用于输入2次密码进行确认情况 |
IPAddress | 验证IPV4地址 |
Length | 验证输入字符长度 |
Optional | 无输入值时跳过其他验证函数 |
Required | 确保字段有值 |
Regxp | 使用正则表达式验证输入值 |
URL | 验证URL |
AnyOf | 确保输入值在可选值列表中 |
NoneOf | 确保输入值不在可选值列表 |
表单渲染成HTML
Flask-Bootstrap提供了一个辅助函数,使用Bootstrap预先定义好的表单样式渲染Flask-Wtf表单对象,使用Bootstrap默认样式渲染传入的表单。
还可以使视图函数渲染表单,接收表单数据
py:
@app.route('/',methods=['GET','POST'])
def index():
name = None
email = None
form = NameForm()
if form.validate_on_submit():
name = form.name.data
email = form.email.data
form.name.data = ''
form.email.data = ''
return render_template('index.html',form=form,name=name)
html:
Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!
{{ wtf.quick_form(form) }}
重定向和用户会话
如果使用上面的视图函数,重复点击链接会再次提交表单,让你确认。
不过可以重定向POST请求,重新向重定向的URL发起GET请求,显示页面内容 - POST/重定向/GET,模式
不过,处理POST请求时,如果不保存数据,下次请求来时,数据就已经丢失。
不过,可以通过用户会话(session)保存数据,并且像python字典一样操作
默认情况下,用户会话保存在cookie中,而且cookie使用SECRET_KEY加密
示范代码:
@app.route('/',methods=['GET','POST'])
def index():
form = NameForm()
if form.validate_on_submit():
session['name'] = form.name.data
session['email'] = form.email.data
return redirect(url_for('index')) # url_for重定向必须是相应视图函数的名字
return render_template('index.html',form=form,name=session.get('name'),email=session.get('email'))
Flash消息
如果状态发生变化,可以通过flash()通知用户 -确认消息,警告或者错误提醒 FLask的核心特性
不过仅仅调用flash()不能把消息显示,还需要模板渲染消息,最好在基模板渲染,这样所有页面都能使用。
py:
@app.route('/',methods=['GET','POST'])
def index():
form = NameForm()
if form.validate_on_submit():
oldname = session['name']
if oldname is not None and oldname!=form.name.data:
flash('Looks like you have changed your name!')
old_email = session['email']
if old_email is not None and old_email !=form.email.data:
flash('Email changed!')
session['name'] = form.name.data
session['email'] = form.email.data
return redirect(url_for('index')) # url_for重定向必须是相应视图函数的名字
return render_template('index.html',form=form,name=session.get('name'),email=session.get('email'))
html:
{% for msg in get_flashed_messages() %}
{{ msg }}
{% endfor %}