wtforms自定义验证器能让字段可选吗?

9 投票
1 回答
7670 浏览
提问于 2025-04-17 08:02

我正在使用一个自定义的验证器来检查某个字段在复选框被选中时是否为空。这个检查是正确的,但无论如何,它总是会验证这个值是否是数字。

简单来说,我需要在表单的某些条件下,让这个字段停止验证。

有没有办法让这个自定义验证器在特定情况下停止对这个字段的验证呢?

1 个回答

16

没错,自定义验证器可以像内置的可选和必填验证器一样控制验证流程。要控制验证流程,你可以使用 StopValidation 这个异常,这样就不会进行进一步的验证了。

如果抛出 StopValidation 时带有消息,它会被添加到错误列表中;如果没有消息,就不会再添加任何错误。

如果你使用的是像 IntegerField、FloatField 这样的字段,也要注意在输入转换时可能出现的“处理错误”。可选验证器处理这个问题的方式是,如果输入为空,它会清除之前的所有错误。我们来快速看看 wtforms/fields.py 中可选验证器的代码:

if not field.raw_data or isinstance(field.raw_data[0], basestring) and not field.raw_data[0].strip():
    field.errors[:] = []
    raise StopValidation()

正如你所看到的,如果没有输入或输入为空,它会清除之前的所有错误。

那么,我们来想想如何实现你的自定义验证器。

from wtforms.validators import StopValidation

def myvalidator(form, field):
    if not form.some_checkbox_field.data:
        # clear out processing errors
        field.errors[:] = []
        # Stop further validators running
        raise StopValidation()

你可以像这样使用你的验证器:

from wtforms import BooleanField, IntegerField, Form, validators as v

class SomeForm(Form):
    some_checkbox_field = BooleanField('Enable MyNumber')
    mynumber = IntegerField('', [myvalidator, v.NumberRange(min=5, max=50)])

所以,如果复选框被选中,它会验证输入的 mynumber 是否是一个数字。此外,NumberRange 验证器也会被执行。如果没有选中复选框,错误会被清除,StopValidation 会阻止 NumberRange 的执行。

撰写回答