使用Flask-WTF创建和渲染表单
Flask-WTF是一个集成了WTForms的Flask扩展,使用它你可以在python文件里创建表单类,然后在HTML使用它提供的函数渲染表单。
跨站请求伪造保护
Flask-WTF默认支持CSRF(跨站请求伪造)保护,只需要在程序中设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证表单中数据的真伪。(关于Flask项目的配置和初始化,后续文章会谈到)你可以使用app.config字典来存储配置变量:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
或是从系统环境变量中获取
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
很多重要的信息,比如邮箱账户和密码都不能直接写在程序里,而要设置系统环境变量,设置方法如下(Windows):
set SECRET_KEY=very very hard to guess string
*Unix用户使用export替换set。
注意,后面的字符串不需要用任何符号括起来。
创建表单
然后我们就可以开始创建表单了,以一个简单的登录表单为例,首先是导入:
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, PasswordField
from wtforms.validators import DataRequired, Length, Email
从Flask-WTF导入Form类,而表单字段和验证函数直接从WTForms导入。
每个表单都用一个继承自Form的类表示,每个字段都用一个对象表示,每个对象可以附加多个验证函数。常见的验证函数有Required(),Length(),Email()等。
在Flask-WTF 0.13版本,引入的表单类为FlaskForm;
在WTForms 3.0版本,验证函数Required变为DataRequired
然后是我们的表单类:
class LoginForm(FlaskForm):
email = StringField(u'邮箱', validators=[
DataRequired(message= u'邮箱不能为空'), Length(1, 64),
Email(message= u'请输入有效的邮箱地址,比如:username@domain.com')])
password = PasswordField(u'密码',
validators=[Required(message= u'密码不能为空')])
submit = SubmitField(u'登录')
在验证函数中传入出错时的提示信息,覆盖默认的英文错误提示。
参考链接:
表单渲染
首先需要在视图函数里引入一个表单类的实例,然后在返回模板的时候,传入这个实例:
@auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
...
return render_template('login.html', form=form)
在HTML文件(login.html)里,我们使用下面的方式来渲染表单:
<form class="form" method="POST">
{{ form.hidden_tag() }}
{{ form.email.label }}{{ form.email() }}
{{ form.password.label }}{{ form.password() }}
{{ form.submit() }}
</form>
这种方式渲染出来的表单没有样式(字段后面的括号里可以填入input属性,如果不填可以省略掉括号,控制表单样式内容见续篇《自定义表单样式》),而且比较繁琐,你也可以使用for循环来遍历字段。
关于form.hidden_tag()
上面说了,Flask-WTF支持跨站请求伪造保护,所以它会为你的表单类自动创建一个CSRF字段,你需要在表单里渲染这个字段:{{ form.csrf_token }}。
而如果你有多个隐藏字段(type属性为hidden)的话,就可以使用{{ form.hidden_tag() }}来渲染所有隐藏字段。
使用Flask-Bootstrap渲染表单
Flask-Bootstrap是一个集成了Bootstrap的Flask扩展,它提供了一些表单渲染的函数,可以让我们方便的渲染Bootstrap样式的表单。
要使用这些函数,首先你要安装Flask-WTF,然后在HTML文件开头引入提供这些函数的模板文件(wtf.html):
{% import 'bootstrap/wtf.html' as wtf %}
使用Flask-Bootstrap提供的wtf.form_field()函数来渲染表单:
{% import "bootstrap/wtf.html" as wtf %}
<form class="form" method="POST">
{{ form.hidden_tag() }}
{{ wtf.form_field(form.title) }}
{{ wtf.form_field(form.body) }}
{{ wtf.form_field(form.submit) }}
</form>
假如你不需要调整Boostrap的默认表单样式,只想要快速生成表单,那么Flask-Bootstrap还提供了一个强大的函数,只需要一行就可以快速生成表单:
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
纯HTML表单或混合
你可以把你想定义的字段与Flask-WTF的渲染字段混在一起,比如像这样直接将确认按钮写在模板里:
<form method="POST">
{{ form.csrf_token }}
{{ form.name.label }} {{ form.name(size=20) }}
<input type="submit" value="确认">
</form>
注:在视图函数里获取数据时,Flask-WTF不验证是否按下了确认按钮,只是判断HTTP方法。
你也可以不使用Flask-WTF,直接把表单写在HTML模板里。这在一些特殊情况下,反而会比使用Flask-WTF更加方便。比如在小项目里,或是需要高度自定义的情况下。在上一个Flask实践项目计时器里,传入时间参数的表单就是直接写在HTML里的:
<form method="POST" action="{{ url_for('custom') }}">
<input type="text" name="time" class="time-input" placeholder="example: 12/30s/20m/2h">
<input type="submit" class="startButton" value="START">
</form>
需要注意的是,这时要给表单添加一个action属性,属性值填写要处理表单数据的视图函数。下一篇文章会详细谈到怎么处理表单的数据。
Flask扩展一般通过安装pip安装(注意要安装在虚拟环境,别忘了激活虚拟环境后再安装):
pip install flask-wtf注意导入时名称的变化,《Flask Web开发》中使用flask.ext.extension_name导入扩展的方式被废弃,使用下面的方式(flask_extension_name)导入扩展中的函数或类:
from flask_wtf import FlaskForm*考虑写一篇文章讲一下扩展的安装、初始化和配置
参考链接
- Cross-site request forgery
- Flask-WTF – Flask-WTF 0.13
- WTForms Documentation
- http://flask.pocoo.org/docs/0.11/patterns/wtforms/
- http://flask.pocoo.org/snippets/category/forms/
– – – – –
更多关于Flask的优质内容,欢迎关注Hello, Flask! – 知乎专栏。