使用 WTForms 進行表單驗證¶
當您必須處理由瀏覽器視圖提交的表單資料時,程式碼很快就會變得難以閱讀。市面上有一些程式庫旨在使此過程更易於管理。其中之一是 WTForms,我們將在此處理它。如果您發現自己處於需要處理許多表單的情況,您可能想試試看。
當您使用 WTForms 時,您必須首先將您的表單定義為類別。我建議將應用程式分解為多個模組(將大型應用程式作為套件)來做到這一點,並為表單新增一個單獨的模組。
表單¶
這是一個典型註冊頁面的範例表單
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),但這當然不是必要條件。請根據需要調整程式碼。
注意事項
如果資料是透過 HTTP
POST
方法提交,則從請求form
值建立表單;如果資料是作為GET
提交,則從請求args
值建立表單。要驗證資料,請呼叫
validate()
方法,如果資料驗證成功,它將傳回True
,否則傳回False
。要從表單存取個別值,請存取
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 %}
此巨集接受一些關鍵字引數,這些引數會轉發到 WTForm 的欄位函式,該函式為我們呈現欄位。關鍵字引數將作為 HTML 屬性插入。因此,例如,您可以呼叫 render_field(form.username, class='username')
以將類別新增到輸入元素。請注意,WTForms 傳回標準 Python 字串,因此我們必須告訴 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 網站。