如何对wtforms字段进行相互验证?

27

我在表单中有三个相同的SelectField输入框,每个输入框都有相同的选项。我不能使用一个多选框。

我想确保用户为这三个字段选择了三个不同的选项。

在自定义验证中,似乎只能一次引用一个字段,无法将此字段的值与其他字段进行比较。我该怎么办?谢谢!

4个回答

34

您可以在您的Form中覆盖validate函数...

class MyForm(Form):
    select1 = SelectField('Select 1', ...)
    select2 = SelectField('Select 2', ...)
    select3 = SelectField('Select 3', ...)
    def validate(self):
        if not Form.validate(self):
            return False
        result = True
        seen = set()
        for field in [self.select1, self.select2, self.select3]:
            if field.data in seen:
                field.errors.append('Please select three distinct choices.')
                result = False
            else:
                seen.add(field.data)
        return result

谢谢 - 为什么要加上 if not Form.validate(self): 这一行呢?我尝试了您的建议,但这一行一直在触发,导致验证无法运行。 - YPCrumble
这是执行默认验证的方法(好像你没有覆盖validate一样)。 - FogleBird
其他步骤是执行跨多个字段的验证,正如您所要求的那样。 - FogleBird
我只想补充一下,我对这里的覆盖感到困惑。参考O'Reilly Learning Python,我会称之为扩展验证方法。因为当你调用if not Form.validate(self)时,仍然会调用默认行为,然后运行自定义验证代码。当我读到这个时,它为我解决了问题。还是@FogleBird给出了很好的答案。 - Jimmy
17
如果你在使用Python 3,最好使用super().validate()而不是Form.validate(self)。如果你在使用Python 2,则应该使用super(MyForm, self).validate() - Dan Passaro

8
您可以在验证表单时使用以下方法获取其他字段的值。
例如:
def validate_name(form, field):
    if form.other_variable.data == 'checked' and len(field.data) > 10:
        raise validation_error("say somgthing")

3
我写了一个小型的Python库required,以使跨字段验证更加容易。您可以将验证逻辑声明性地编码为成对依赖项。因此,您的表单可能如下所示:
from required import R, Requires, RequirementError

class MyForm(Form):

    VALIDATION = (
        Requires("select1", R("select1") != R("select2") +
        Requires("select2", R("select2") != R("select3") +
        Requires("select3", R("select3") != R("select1")
    )

    select1 = SelectField('Select 1', ...)
    select2 = SelectField('Select 2', ...)
    select3 = SelectField('Select 3', ...)

    def validate(self):
        data = {
            "select1": self.select1.data,
            "select2": self.select2.data,
            "select3": self.select3.data,
        }

        # you can catch the RequirementError
        # and append the error message to 
        # the form errors

        self.VALIDATION.validate(data)
        return result

您可以使用 VALIDATION 对象并添加更多的验证规则,甚至可以将其放在单独的模块中,并在不同的地方导入/重用验证规则。


0

使用 FieldList 如下:

def field_level(form, field):
    all_values = form.selects.data
    value = field.data

def list_level(form, field):
    all_values = field.data

class MyForm(Form):
    selects = FieldList(SelectField('label', validators=[field_level]), validators=[list_level])

form = MyForm()
form.append_entry()
form.append_entry()
form.append_entry()

您可以在字段级别和字段列表级别上设置验证器


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接