自定義驗證器
在WTForms中,驗證器是指在定義字段時傳入validators參數列表的可調用對象,下面來看下編寫自定義驗證器。
行內驗證器
除了使用WTForms提供的驗證器來驗證表單字段,我們還可以在表單類中定義方法來驗證特定字段,例如:
form/form.py: 針對特定字段的驗證器
from wtforms import IntegerField, submitField from wtforms.validators import validationError class FortyTwoForm(FlaskForm): answer = IntegerField('The Number') submit = SubmitField() def validate_answer(form, field): if field.data != 42: raise validationError('Must be 42.')
當表單類中包含以“validate_字段屬性名”形式命名的方法時,在驗證字段數據時會同時調用這個方法來驗證對應的字段,因為這一點,表單類的字段名不能以validate開頭。驗證方法接受兩個位置參數,一次為form和field,前者為表單類實例,后者是字段對象,我們可以通過field.data獲取字段數據,這兩個參數將在驗證表單時被調用傳入。驗證出錯時拋出從wtforms.validators模塊導入的ValidationError異常,傳入錯誤消息作為參數。因為這種方法僅用來驗證特定的表單類實例,所以又稱為行內驗證器。
定義視圖函數:
@app.route('/basic_macro',methods=['GET','POST']) def basic_macro(): form = FortyTwoForm() if form.validate_on_submit(): return redirect(url_for('hello')) return render_template('basic_macro.html', form=form)
basic_macro.html中修改渲染字段:
<form method="post"> {{ form.csrf_token }} {{ form_field(form.answer) }}<br> {{ form.submit }}<br> </form>
訪問127.0.0.1:5000/basic_macro
提交空格:
如果把自定義驗證器函數注釋掉,則驗證時顯示如下,沒有額外的提示
全局驗證器
如果想要創建一個可重用的通用驗證器,可以通過定義一個函數來實現。如果不需要傳入參數定義驗證器,那么一個和表單類中定義的驗證方法完全相同的函數就足夠了,例如:
在app.py中定義一個is_41()驗證器函數,在FortyOneForm表單類中定義字段時傳入這個驗證器,在提交表單時會調用這個驗證器進行調用
from wtforms import IntegerField, SubmitField from wtforms.validators import ValidationError def is_41(form, field): if field.data != 41: raise ValidationError('Must be 41') class FortyOneForm(FlaskForm): answer = IntegerField('The Number', validators=[is_41]) submit = SubmitField()
當使用函數定義全局的驗證器時,我們需要在定義字段時在validators列表里傳入這個驗證器。因為在validators列表中傳入的驗證器必須是可調用對象,所以這里傳入了函數對象,而不是函數調用。
在實際應用時,通常需要讓驗證器支持傳入傳參數來對驗證過程進行設置。
至少應該支持message參數來設置自定義錯誤消息。這時驗證函數應該實現成工廠函數,即返回一個可調用對象的函數,比如:
工廠函數形式的全局驗證器:
from wtforms import IntegerField, SubmitField from wtforms.validators import ValidationError def is_41(message=None): if message is None: message = 'Must be 41.' def _is_41(form, field): if field.data != 41: raise ValidationError(message) return _is_41 class FortyOneForm(FlaskForm): answer = IntegerField('The Number', validators=[is_41()]) submit = SubmitField()
在現在的is_41()函數中,我們創建了另一個_is_41()函數,這個函數胡作為被調用對象返回。is_41()函數接收的message參數用來傳入自定義錯誤消息,默認為None,如果沒有設置就使用內置消息。在validators列表中,這時要傳入的是對工廠函數is_41()的調用。
用默認的參數時,訪問/basic_macro路徑:
在is_41()函數中傳入參數,再次訪問,頁面提示內容就會顯示傳入的內容:
class FortyOneForm(FlaskForm): answer = IntegerField('The Number', validators=[is_41("Wrong input, it should be 41")]) submit = SubmitField()