使用 WTForms 进行表单验证

当你必须处理浏览器提交的表单数据时,视图代码很快会变得难以阅读。有一些库可以简化这个工作, WTForms 便是其中之一 ,下面我们将介绍这个库。如果你必须处理许多表单,那么应当尝试使用这个库。

如果要使用 WTForms ,那么首先要把表单定义为类。我推荐把应用分割为多个模块(大型应用 ),并为表单添加一个独立的模块。

使用一个扩展获得大部分 WTForms 的功能

Flask-WTF 扩展可以实现本方案的所有功能,并且还提供一些辅助小工具。使用这个扩展可以更好的使用表单和 Flask 。你可以从 PyPI 获得这个扩展。

表单

下面是一个典型的注册页面的示例:

  1. from wtforms import Form, BooleanField, StringField, PasswordField, validators
  2. class RegistrationForm(Form):
  3. username = StringField('Username', [validators.Length(min=4, max=25)])
  4. email = StringField('Email Address', [validators.Length(min=6, max=35)])
  5. password = PasswordField('New Password', [
  6. validators.DataRequired(),
  7. validators.EqualTo('confirm', message='Passwords must match')
  8. ])
  9. confirm = PasswordField('Repeat Password')
  10. accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])

视图

在视图函数中,表单用法示例如下:

  1. @app.route('/register', methods=['GET', 'POST'])
  2. def register():
  3. form = RegistrationForm(request.form)
  4. if request.method == 'POST' and form.validate():
  5. user = User(form.username.data, form.email.data,
  6. form.password.data)
  7. db_session.add(user)
  8. flash('Thanks for registering')
  9. return redirect(url_for('login'))
  10. return render_template('register.html', form=form)

注意,这里我们默认视图使用了 SQLAlchemy ( 使用 SQLAlchemy ),当然这不是必须的。请根据你的实际情况修改代码。

请记住以下几点:

  • 如果数据是通过 HTTP POST 方法提交的,请根据form 的值创建表单。如果是通过 GET 方法提交的,则相应的是 args

  • 调用 validate() 函数来验证数据。如果验证通过,则函数返回 True ,否则返回 False

  • 通过 form..data 可以访问表单中单个值。

模板中的表单

现在我们来看看模板。把表单传递给模板后就可以轻松渲染它们了。看一看下面的示例模板就可以知道有多轻松了。 WTForms 替我们完成了一半表单生成工作。为了做得更好,我们可以写一个宏,通过这个宏渲染带有一个标签的字段和错误列表(如果有的话)。

以下是一个使用宏的示例 _formhelpers.html 模板:

  1. {% macro render_field(field) %}
  2. <dt>{{ field.label }}
  3. <dd>{{ field(**kwargs)|safe }}
  4. {% if field.errors %}
  5. <ul class=errors>
  6. {% for error in field.errors %}
  7. <li>{{ error }}</li>
  8. {% endfor %}
  9. </ul>
  10. {% endif %}
  11. </dd>
  12. {% endmacro %}

上例中的宏接受一堆传递给 WTForm 字段函数的参数,为我们渲染字段。参数会作为 HTML属性插入。例如你可以调用 render_field(form.username, class='username') 来为输入元素添加一个类。注意: WTForms 返回标准的 Python unicode 字符串,因此我们必须使用 |safe 过滤器告诉 Jinja2 这些数据已经经过 HTML 转义了。

以下是使用了上面的 _formhelpers.htmlregister.html 模板:

  1. {% from "_formhelpers.html" import render_field %}
  2. <form method=post>
  3. <dl>
  4. {{ render_field(form.username) }}
  5. {{ render_field(form.email) }}
  6. {{ render_field(form.password) }}
  7. {{ render_field(form.confirm) }}
  8. {{ render_field(form.accept_tos) }}
  9. </dl>
  10. <p><input type=submit value=Register>
  11. </form>

更多关于 WTForms 的信息请移步 WTForms 官方网站