Flask-WTForms RadioField自定义验证器消息不起作用

时间:2016-09-26 07:02:10

标签: python flask flask-wtforms

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")])

错误消息

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

因此对于TextField,它会显示自定义错误消息。

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

1 个答案:

答案 0 :(得分:3)

你说这个过程是不同的。

因此,如果您执行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个方法。然后当RadioField继承自SelectField时,它也拥有它。

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()错误而不是自定义错误的原因,因为它只是没有通过{{1}它停止了。

注意pre_validate()验证程序已被删除,将在WTForms 3.0中删除,并且在that拉取请求中,它们已将其删除了。使用Required

代替Required()验证程序

更新:由于您将验证程序添加到字段,因此您仍然可以收到错误消息。因为pre_validate()只提出DataRequired(),所以它不会停止validate()

ValueError

然后转到

# 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合并到主数据库时修复。< / p>