Flask有众多的扩展来简化集成各种常用的库和框架,比如Flask-Bootstrap集成了Bootstrap,Flask-WTF集成了WTForms。这篇要介绍的就是Flask-WTF。
安装和配置
安装很简单,使用pip:
pip install flask-wtf
Flask-WTF默认支持CSRF(跨站请求伪造)保护,只需要在程序中设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证表单中数据的真伪。(关于Flask项目的配置和初始化,后续文章会谈到)你可以使用app.config字典来存储配置变量:
1 2 3 |
app = Flask(__name__) app.config['SECRET_KEY'] = 'hard to guess string' |
或是从系统环境变量中获取
1 2 3 |
app = Flask(__name__) app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY') |
很多重要的信息,比如邮箱账户和密码都不能直接下载程序里,而要设置系统环境变量,设置方法如下(Windows CMD):
1 2 |
set SECRET_KEY=very very hard to guess string |
后面的字符串不需要用任何符号括起来。
表单
每个表单都用一个继承自Form的类表示,每个字段都用一个对象表示,每个对象可以附加多个验证函数。常见的验证函数有Required()
,Length()
,Email()
等。
一个登录表单示例:
1 2 3 4 5 6 7 8 9 |
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'登录') |
渲染表单
表单有很多种渲染方式。
下面以一个撰写文章的表单为例。
默认的渲染方式
1 2 3 4 5 6 7 |
<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),可以让你快速生成样式良好的表单。
1 2 3 4 5 6 7 8 |
{% 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还提供了一个强大的函数,只需要一行就可以快速生成表单):
1 2 3 |
{% import "bootstrap/wtf.html" as wtf %} {{ wtf.quick_form(form) }} |
控制表单的样式
对于样式,可以通过给表单增加id或class来实现。比如这样:
1 2 3 |
{{ form.body.label }}{{ form.body(class="post-body") }} # 默认渲染 {{ wtf.form_field(form.body, class="post-body") }} # 使用Flask-Bootstrap渲染 |
也可以在表单类里传入参数,像这样:
1 2 |
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,得确保表单字段使用默认的渲染方式。
提交表单视图
这是一个添加文章的视图。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@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) |
常见问题索引
- 一个页面里有多个表单
- 文件及多文件上传
- 文本编辑器支持