Flask-WTF对WTForms包进行了包装,很好的集成到Flask程序中。
在虚拟环境中使用pip工具安装Flask-WTF:
(venv) $ pip install flask-wtf
为应用设置配置的方法有很多种,最简单的解决方式就是在app.config中将变量以键的形式定义,也就是用字典的样式处理变量。比如这样:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'you-will-never-guess'
# ... add more variables here as needed
用类的方式存储配置变量有助于后续的拓展,在主目录新建一个名为 config.py 的Python模块,把配置变量存在这里:
import os
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
Flask及一些其他的拓展将 SECRET_KEY 配置变量作为加密密钥,用于生成签名或令牌。FLASK-WTF用它来保护web表单免遭恶意攻击,这叫跨站点请求伪造(Cross-Site Request Forgery / CSRF,发音为“seasurf”)。顾名思义,密钥应该是保密的,因为它所生成的令牌和签名的强度取决于除了应用程序受信任的管理员之外没人知道。
密钥的值分为两部分,用 or 连接,程序会先从环境变量中查找 SECRET_KEY, 如果没有,就会使用后面的硬编码字符串。这种模式在后面会频繁使用。
现在在应用初始化语句后面使用 app.config.from_object() 方法来应用配置:
from flask import Flask
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
from app import routes
Flask-WTF拓展用Python类来代表web表单,以表单类的类变量的形式定义表单的字段。
下面是一个登录表单:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In')
此处导入的四个代表表单字段类型的类是直接从WTForms包导入的,每个字段都是作为LoginForm类的类变量创建。每个字段的第一个参数代表简介和标签。
可选的 validators 参数用于验证字段。DataRequired验证器用于检测提交是否为空。
app/templates/login.html
{% extends "base.html" %}
{% block content %}
Sign In
{% endblock %}
form.hidden_tag() 模板参数生成包含用于保护表单免受CSRF攻击的令牌的隐藏字段。
下面编写映射到 /login URL的视图函数:
from flask import render_template
from app import app
from app.forms import LoginForm
# ...
@app.route('/login')
def login():
form = LoginForm()
return render_template('login.html', title='Sign In', form=form)
从 forms.py 导入 LoginForm表单类,并将其实例化,form=form 向模板传递 form 对象。
app/routes.py
from flask import render_template, flash, redirect
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
flash('Login requested for user {}, remember_me={}'.format(
form.username.data, form.remember_me.data))
return redirect('/index')
return render_template('login.html', title='Sign In', form=form)
路由装饰器中的methods参数代表这个视图函数接收 GET 和 POST 请求,如果没有显式的定义,则默认接受 GET 请求。
form.validate_on_submit() 方法进行所有的表单处理工作。当浏览器发送的是 GET 请求时,这个方法会返回False。
当浏览器发送的是 POST 请求时, form.validate_on_submit() 会对所有的数据进行相应的验证,如果有任何一个字段验证没通过,这个函数会返回False,如果验证都通过,会返回 True, 并交由应用程序处理。
当 form.validate_on_submit() 返回的是 True, 登录视图函数会调用两个新的函数,从Flask导入。flash()函数可以向用户提示信息。
第二个函数是 redirect()。这个函数可以让浏览器重定向到其他页面。
{% if title %}
{{ title }} - microblog
{% else %}
microblog
{% endif %}
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
- {{ message }}
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}