渲染表单模板
WTForms 和 Flask-WTF 提供了将 Python 表单对象渲染成 HTML 表单模板的功能。这里以登录为例,先来实现一个登录的表单类,代码如下。
from wtforms import Form, StringField, BooleanField, SubmitField, ValidationError
from flask_wtf import FlaskForm
from wtforms.validators import Email, Length
class LoginForm(FlaskForm):
email = StringField(
label="邮箱:",
validators=[Email(message="请输入正确格式的邮箱!")],
render_kw={"placeholder": "请输入邮箱"}
)
password = StringField(
label="密码:",
validators=[Length(min=6, max=20, message="请输入正确长度的密码!")],
render_kw={"placeholder": "请输入密码"}
)
remember = BooleanField(label="记住我:")
submit = SubmitField(label="提交")
这里定义了一个 LoginForm 类,并使其继承自 FlaskForm 类。FlaskForm 的父类是 wtforms.Form 类,其在 wtforms.Form 类的基础上增加了一些方便的方法,以使在验证表单数据时,不再需要手动传入 request.form。接着分别定义了 email、password、remember 和 submit 这 4 个字段,这 4 个字段都新增了一个 label 参数,这个参数在渲染表单模板时会为除 submit 以外的字段生成一个 label 标签,因为 submit 是一个提交按钮,在提交按钮中 label 参数会被设置成属性 value 的值。如果在表单标签上设置一些属性,如 placeholder,可以通过参数 render_kw 来实现。
表单类定义好后,就可以在视图函数中使用了,因为现在表单类跟模板深度结合,所以使用方式跟之前有所不同,先看如下示例代码。
from forms import RegisterForm, LoginForm
from flask import Flask, render_template, redirect
@app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm(meta={"csrf": False})
if form.validate_on_submit():
email = form.email.data
password = form.password.data
return redirect("/")
return render_template("login.html", form=form)
上述代码中,先定义了一个 login 视图函数,并使得其同时支持 GET 和 POST 请求。然后创建了一个 LoginForm 对象,并且通过传递 meta 参数,关闭了 CSRF 验证(关于 CSRF, 6.3节会讲到,这里先关闭即可)。我们重点关注渲染模板的代码,这里把 form 对象传给了 login.html 模板,而在 login.html 模板中,现在就可以使用 form 对象来渲染表单元素了,代码如下。

上述代码中,首先通过 form.<字段名>.label 渲染了 email、password 和 remember 这 3 个字段的 label 标签,然后通过 form.<字段名> 渲染对应的 input 标签。在每个字段下面循环 form.<字段名>.errors 进行验证,如果验证出现错误,会把所有的错误信息展示出来。然后我们再回过头去看 login 视图函数,重点关注表单验证部分的代码。
def login():
form = LoginForm(meta={"csrf": False})
if form.validate_on_submit():
email = form.email.data
password = form.password.data
return redirect("/")
return render_template("login.html", form=form)
以上代码中,通过调用 form.validate_on_submit() 方法判断是否通过 POST 请求使表单验证成功,如果验证通过,则进入下一步操作,否则依然渲染 login.html 模板。其实此时的 form 上已经保存了验证失败的错误信息,因为在模板中通过 form.<字段名>.errors 已经获取到了对应字段的错误信息。所以如果访问 http://127.0.0.1:5000/login ,不输入任何数据,并直接单击 “提交” 按钮,可以看到如图 6-3 所示的效果。

如果输入正确格式的邮箱和密码,再单击“提交”按钮,则会跳转到首页。
关于使用 WTForms 和 Flask-WTF 在模板中渲染表单,个人不太推荐。在 Python 类中定义 HTML 标签及其样式,会提高代码间的耦合度,造成本应在 HTML 模板中完成的工作,却要在 Python 文件中修改,特别是在前后端开发工程师共同开发项目的情况下,这种项目结构的缺点更是异常突出。 |