Flask 使用 WTForms 進(jìn)行表單驗(yàn)證

2021-08-11 10:11 更新

如果您不得不跟瀏覽器提交的表單數(shù)據(jù)打交道,視圖函數(shù)里的代碼將會(huì)很快變得 難以閱讀。有不少的代碼庫(kù)被開(kāi)發(fā)用來(lái)簡(jiǎn)化這個(gè)過(guò)程的操作。其中一個(gè)就是 WTForms , 這也是我們今天主要討論的。如果您發(fā)現(xiàn)您自己陷入處理很多表單的境地,那您也許 應(yīng)該嘗試一下他。

要使用 WTForms ,您需要先將您的表單定義為類。我建議您將應(yīng)用分割為多個(gè)模塊 (大型應(yīng)用) ,這樣的話您僅需為表單添加一個(gè)獨(dú)立的模塊。

挖掘 WTForms 的最大潛力

Flask-WTF 擴(kuò)展在這個(gè)模式的基礎(chǔ)上擴(kuò)展并添加了一些隨手即得的精巧 的幫助函數(shù),這些函數(shù)將會(huì)使在 Flask 里使用表單更加有趣,您可以通過(guò) PyPI 獲取它。

表單

以下是一個(gè)典型的注冊(cè)頁(yè)面的例子:

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

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

在視圖里

在視圖函數(shù)中,表單的使用是像下面這個(gè)樣子的:

@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 )。但是 這并非必要的,請(qǐng)按照您的需要修正代碼。

備忘表:

  1. 如果數(shù)據(jù)是以 POST 方式提交的,那么基于請(qǐng)求的 form 屬性的值創(chuàng)建表單。反過(guò)來(lái),如果是使用 GET 提交的,就從 args 屬性創(chuàng)建。
  2. 驗(yàn)證表單數(shù)據(jù),調(diào)用 validate() 方法。如果數(shù)據(jù)驗(yàn)證 通過(guò),此方法將會(huì)返回 True ,否則返回 False 。
  3. 訪問(wèn)表單的單個(gè)值,使用 form.<NAME>.data 。

在模板中使用表單

在模板這邊,如果您將表單傳遞給模板,您可以很容易地渲染他們。參看如下代碼, 您就會(huì)發(fā)現(xiàn)這有多么簡(jiǎn)單了。WTForms 已經(jīng)為我們完成了一半的表單生成工作。更 棒的是,我們可以編寫一個(gè)宏來(lái)渲染表單的字段,讓這個(gè)字段包含一個(gè)標(biāo)簽,如果 存在驗(yàn)證錯(cuò)誤,則列出列表來(lái)。

以下是一個(gè)使用這種宏的 _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 %}

這些宏接受一對(duì)鍵值對(duì),WTForms 的字段函數(shù)接收這個(gè)宏然后為我們渲染他們。 鍵值對(duì)參數(shù)將會(huì)被轉(zhuǎn)化為 HTML 屬性,所以在這個(gè)例子里,您可以調(diào)用 render_field(form.username,class="username") 來(lái)將一個(gè)類添加到這個(gè) 輸入框元素中。請(qǐng)注意 WTForms 返回標(biāo)準(zhǔn) Python unicode 字符串,所以我們 使用 |safe 告訴 Jinjan2 這些數(shù)據(jù)已經(jīng)是經(jīng)過(guò) HTML 過(guò)濾處理的了。

以下是 register.html 模板,它對(duì)應(yīng)于上面我們使用過(guò)的函數(shù),同時(shí)也利用 了 _formhelpers.html 模板:

{% from "_formhelpers.html" import render_field %}
<form method=post action="/register">
  <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>

關(guān)于 WTForms 的更多信息,請(qǐng)?jiān)L問(wèn) WTForms 網(wǎng)站 。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)