Flask有众多的扩展来简化集成各种常用的库和框架,比如Flask-Bootstrap集成了Bootstrap,Flask-WTF集成了WTForms。这篇要介绍的就是Flask-WTF。
安装和配置
安装很简单,使用pip:
pip install flask-wtf
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 CMD):
set SECRET_KEY=very very hard to guess string
后面的字符串不需要用任何符号括起来。
表单
每个表单都用一个继承自Form的类表示,每个字段都用一个对象表示,每个对象可以附加多个验证函数。常见的验证函数有Required()
,Length()
,Email()
等。
一个登录表单示例:
from flask_wtf import Form # 导入Form
from wtforms import StringField, SubmitField, RadioField, PasswordField, BooleanField # 导入字段
from wtforms.validators import Required, Length, Email # 导入验证函数
class LoginForm(Form):
email = StringField(u'邮箱', validators=[Required(message= u'邮箱不能为空'), Length(1, 64), Email(message= u'请输入有效的邮箱地址,比如:username@domain.com')])
password = PasswordField(u'密码', validators=[Required(message= u'密码不能为空')])
remember_me = BooleanField(u'记住我')
submit = SubmitField(u'登录')
渲染表单
表单有很多种渲染方式。
下面以一个撰写文章的表单为例。
默认的渲染方式
<form class="form" method="POST">
{{ form.hidden_tag() }}
{{ form.title.label }}{{ form.title() }}
{{ form.body.label }}{{ form.body() }}
{{ form.submit() }}
</form>
这种方式渲染出来的表单没有样式,而且很繁琐(当然,你也可以使用for循环来遍历字段)。
使用Flask-Bootstrap渲染
Flask-Bootstrap提供了一个模板(wtf.html),可以让你快速生成样式良好的表单。
{% 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) }}
控制表单的样式
对于样式,可以通过给表单增加id或class来实现。比如这样:
{{ form.body.label }}{{ form.body(class="post-body") }} # 默认渲染
{{ wtf.form_field(form.body, class="post-body") }} # 使用Flask-Bootstrap渲染
也可以在表单类里传入参数,像这样:
body = TextAreaField(u'正文', validators=[Required(u'内容不能为空!')], render_kw={'rows': 20, 'placeholder': u'你有什么想法?'})
在表单字段里传入一个render_kw字典,将HTML的参数和值以键值对的形式写入字典。WTForms2.1及以上版本适用。
这里需要注意的是,Flask-Bootstrap会给表单添加class来控制样式,这时你再通过render_kw传入已经被定义过的参数会失败。所以,如果要使用render_kw传入class,得确保表单字段使用默认的渲染方式。
提交表单视图
这是一个添加文章的视图。
@main.route('/new/post', methods=['GET', 'POST'])
@login_required
def new_post():
form = PostForm()
if form.validate_on_submit():
post = Post(
title = form.title.data,
body = form.body.data)
db.session.add(post)
db.session.commit()
return redirect(url_for('.post', id=post.id))
return render_template('edit/new_post.html', form=form)
常见问题索引
- 一个页面里有多个表单
- 文件及多文件上传
- 文本编辑器支持