2016-09-26 115 views
2

Flask-WTForms中,我們可以爲每個字段的每個驗證器提供自定義消息。但對於RadioField,它僅顯示默認消息。下面是一個例子。Flask-WTForms RadioField自定義驗證器消息不起作用

>>> from wtforms import Form, RadioField, TextField 
>>> from wtforms.validators import * 

的TextField

>>> class MyForm(Form): 
     x = TextField(u'Some text', validators = [Required(message="Hello")]) 

錯誤消息所以對於一個TextField

>>> form = MyForm() 
>>> form.x.data 
>>> form.validate() 
False 
>>> form.errors 
{'x': ['Hello']} 

它示出了定製的錯誤消息。

RadioField

>>> class MyForm(Form): 
     x = RadioField(choices = [(1, '1'), (2, '2')], validators = [Required(message="Hello")]) 

錯誤消息

>>> form = MyForm() 
>>> form.x.data 
u'None' 
>>> form.validate() 
False 
>>> form.errors 
{'x': [u'Not a valid choice']} 

定製錯誤消息是不存在。我想,驗證TextFieldRadioField將是不同的過程,可能是這就是它顯示默認消息的原因。

所以我的問題是如何顯示驗證RadioField的自定義消息?

+0

您是否找到解決方案? – roy

+0

我試圖修改源代碼,但沒有解決方案。 – RatDon

回答

1

你是對的,這個過程是不同的。

所以,如果你去做source code有基Field類與validate方法。據說

""" 
Validates the field and returns True or False. `self.errors` will 
contain any errors raised during validation. This is usually only 
called by `Form.validate`. 

Subfields shouldn't override this, but rather override either 
`pre_validate`, `post_validate` or both, depending on needs.> 

:param form: The form the field belongs to. 
:param extra_validators: A sequence of extra validators to run. 
""" 

和驗證的過程是pre_validate() - >validate() - >post_validate()(呼叫pre_validate - >運行驗證 - >通話post_validate

正如您可以猜到,RadioField有它的自己的pre_validate()方法,但基本上是SelectField的一個。然後當RadioFieldSelectField繼承時,它也有。

def pre_validate(self, form): 
    for v, _ in self.choices: 
     if self.data == v: 
      break 
    else: 
     raise ValueError(self.gettext('Not a valid choice')) 

所以這就是爲什麼你自定義一個'Not a valid choice'錯誤,而不是上wtforms.validators.Required()驗證,因爲它只是沒有經過pre_validate()和停止。

Required驗證器depracated,將在WTForms 3.0中被移除,並在that拉請求他們已經刪除,但是使用。取而代之的Required()驗證,使用DataRequired()

UPDATE:既然你把你的驗證仍然字段中應該能夠得到您的錯誤。因爲自pre_validate()只有ValueError提高它不會停止validate()

# Call pre_validate 
try: 
    self.pre_validate(form) 
except StopValidation as e: 
    if e.args and e.args[0]: 
     self.errors.append(e.args[0]) 
    stop_validation = True 
except ValueError as e: 
    self.errors.append(e.args[0]) 

然後它去

# Run validators 
if not stop_validation: 
    chain = itertools.chain(self.validators, extra_validators) 
    stop_validation = self._run_validation_chain(form, chain) 

,這是你的驗證存在,應該添加新的錯誤到錯誤列表(form.x.error),但它會將None轉換爲'None',所以你form.x.data變得'None'str型),現在它去__call__

def __call__(self, form, field): 
    if not field.data or isinstance(field.data, string_types) and not field.data.strip(): 
     if self.message is None: 
      message = field.gettext('This field is required.') 
     else: 
      message = self.message 

     field.errors[:] = [] 
     raise StopValidation(message) 

然後,條件not field.dataFalse,因爲field.data'None'。 爲什麼數據從None轉換爲'None'SelectField,其相關的數據在Issue on GitHub中進行了說明,並且當Pull Request將在主數據庫中合併時可能會被修復。

+0

感謝您的信息。我在代碼中用'DataRequired()'代替。但是,如何覆蓋'RadioField'驗證的默認消息?我需要定義一個自定義方法嗎? – RatDon

+1

@RatDon我已經更新了這個問題。您的方法沒有任何問題,您仍然應該能夠看到您的自定義消息以及「不是有效的選擇」。但是,事情與'SelectField'及其親戚有點混亂。所以現在你的選擇之一是手動檢查'form.x.data'是否爲'None'。另一個是使用[那個fork](https://github.com/georgschoelly/wtforms/tree/no_coerce_none)[pull](https://github.com/wtforms/wtforms/pull/288) –

+0

Got源和修改,如拉提到的。但沒有效果。 :-( – RatDon