
Flask-WTF扩展可以把处理web表单的过程变成一种愉悦的体验。

默认情况下,Flask-WTF能够保护所有表单免受跨站请求伪造的攻击。恶意网站把请求发送到被攻击者已登录的网站时就会引起CSRF攻击。
为了实现CSRF保护,Flask-WTF需要程序设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。设置密钥的方法如下所示:
app = Flask(__name__)
app.config['SECRET_KEY']='hard to guess string'使用Flask-WTF时,每个web表单都由一个继承自Form的类表示。这个定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数。验证函数用来验证用户提交的输入值是否符合要求。
#!/usr/bin/env python
#简单的web表单,包含一个文本字段和一个提交按钮
from flask_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')StringField类表示属性为type="text"的<input>元素,SubmitField类表示属性为type="submit"的<input>元素。
WTForms支持的HTML标准字段
| 字段类型 | 说明 | 
|---|---|
| StringField | 文本字段 | 
| TextAreaField | 多行文本字段 | 
| PasswordField | 密码文本字段 | 
| HiddenField | 隐藏文本字段 | 
| DateField | 文本字段,值为datetime.date格式 | 
| IntegerField | 文本字段,值为整数 | 
| FloatField | 文本字段,值为浮点数 | 
| SelectField | 下拉列表 | 
| SubmitField | 表单提交按钮 | 
WTForms验证函数
| 验证函数 | 说明 | 
|---|---|
| 验证电子邮件地址 | |
| EqualTo | 比较两个字段的值,常用于要求输入两次密码进行确认的情况 | 
| IPAddress | 验证IPv4网络地址 | 
| Length | 验证输入字符串的长度 | 
| NumberRange | 验证输入的值在数字范围内 | 
| Optional | 无输入值时跳过其他验证函数 | 
| Required | 确保字段中有数据 | 
| Regexp | 使用正则表达式验证输入值 | 
| URL | 验证URL | 
| AnyOf | 确保输入值在可选值列表中 | 
| NoneOf | 确保输入值不在可选值列表中 | 
表单字段是可用的,在模板中调用后会渲染成HTML。假设视图函数把一个NameForm实例通过参数form传入模板,在模板中可以生成一个简单的表单,如下所示:
<form method="POST">
    {{ form.hidden_tag() }}
    {{ form.name.label }} {{ form.name() }}
    {{ form.submit() }}
</form><form method="POST">
    {{ form.hidden_tag() }}
    {{ form.name.label }} {{ form.name(id='my-text-field') }}
    {{ form.submit() }}
</form>Flask-Bootstrap提供了一个非常高端的辅助函数,可以使用Bootstrap中预先定义好的表单样式渲染整个Flask-WTF表单,而这些操作只需调用一次即可完成。
{% import "boostrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}#使用Flask-WTF和Flask-Bootstrap渲染表单
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Flasky{% endblock %}
{% block page_content %}
<div class="page-header">
    <h1>Hello,{% if name %}{{ name }}{% else %}Stranger{% endif %}</h1>
</div>
{{ wtf.quick_form(form) }}
{% endblock %}@app.route('/',methods=['GET','POST'])
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        name = form.name.data
        form.name.data = ''
    return render_template('index.html',form=form,name=name)app.route修饰器中添加的methods参数告诉Flask在URL映射中把这个视图函数注册为GET和POST请求的处理程序。如果没指定methods参数,就只把视图函数注册为GET请求的处理程序。
#!/usr/bin/env python
from flask import Flask,render_template,session,redirect,url_for
app = Flask(__name__)
@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'))例子:提示用户名或密码错误,弹出窗口
from flask import Flask,render_template,session,redirect,url_for,flash
app = Flask(__name__)
@app.route('/',methods=['GET','POST'])
def index():
    form = NameForm()
    if form.validata_on_submit():
        old_name = session.get('name')
        if old_name is not None and old_name != form.name.data:
            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'))#渲染Flash消息
{% block content %}
<div class="container">
    {% 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 %}