使用WTForms进行表单验证

如果您不得不跟浏览器提交的表单数据打交道,视图函数里的代码将会很快变得 难以阅读。 有在图书馆设计使这个过程更容易管理。其中一个是WTForms,我们将在这里处理。 如果您发现您自己陷入处理很多表单的境地,那您也许 应该尝试一下他。

要使用 WTForms ,您需要先将您的表单定义为类。 我建议您将应用分割为多个模块 (大型应用) ,这样的话您仅需为表单添加一个独立的模块。

挖掘 WTForms 的最大潜力

Flask-WTF扩展扩展了这个模式,并添加了一些小助手,使表单和Flask更有趣。你可以从PyPI得到它。

表单

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

from wtforms import Form, BooleanField, StringField, PasswordField, validators

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

在视图中

在视图函数中,表单的使用是像下面这个样子的:

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

注意到我们视图中使用了 SQLAlchemy (参考 在 Flask 中使用 SQLAlchemy )。 但是 这并非必要的,请按照您的需要修正代码。

注意事项:

  1. create the form from the request form value if the data is submitted via the HTTP POST method and args if the data is submitted as GET.
  2. 要验证数据,请调用validate()方法,如果数据有效,则返回True,否则返回False
  3. 访问表单的单个值,使用 form.<NAME>.data

模板中的表单

现在到模板端。 在模板这边,如果您将表单传递给模板,您可以很容易地渲染他们。 参看如下代码, 您就会发现这有多么简单了。 WTForms 已经为我们完成了一半的表单生成工作。 更 棒的是,我们可以编写一个宏来渲染表单的字段,让这个字段包含一个标签,如果 存在验证错误,则列出列表来。

以下是使用此宏的示例_formhelpers.html

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

这些宏接受一对键值对,WTForms 的字段函数接收这个宏然后为我们渲染他们。 关键字参数将作为HTML属性插入。因此,例如,您可以调用render_field(form.username, class ='username')以向输入元素添加类。注意,WTForms返回标准的Python unicode字符串,所以我们必须告诉Jinja2这个数据已经使用|safe过滤器进行HTML转义。

这里是我们上面使用的函数的register.html模板,它利用了_formhelpers.html模板:

{% from "_formhelpers.html" import render_field %}
<form method=post>
  <dl>
    {{ render_field(form.username) }}
    {{ render_field(form.email) }}
    {{ render_field(form.password) }}
    {{ render_field(form.confirm) }}
    {{ render_field(form.accept_tos) }}
  </dl>
  <p><input type=submit value=Register>
</form>

有关WTForms的更多信息,请转到WTForms网站