WTForms-JSON,使用FormField可选嵌套

时间:2014-01-09 21:54:35

标签: wtforms wtforms-json

我正在使用WTForms-JSON并处理嵌套表单。我想使内部表单可选,但如果内部表单存在,我希望它的字段是必需的。我遇到的问题是FormField不接受验证器。

(虽然我使用的是WTForms-JSON,但我相信这也适用于vanilla WTForms。)

此代码有效但行为不符合我的要求:

class InnerForm(Form):
    foo_id = IntegerField("Foo ID", [Required()])

class OuterForm(Form):
    inner = FormField(InnerForm)

上述代码的问题是隐式需要inner。奇怪的是,validate()在省略False时返回innererrors为空。

此代码不起作用:

class InnerForm(Form):
    foo_id = IntegerField("Foo ID", [Required()])

class OuterForm(Form):
    inner = FormField(InnerForm, "Inner", [Optional()])

后者产生此错误:

TypeError: FormField does not accept any validators. Instead, define them on the enclosed form.

我的问题是:我如何使inner成为可选项,但如果foo_id存在则需要inner

3 个答案:

答案 0 :(得分:3)

最简单的方法是将FormField包裹在FieldList中,max_entries设置为1. FieldList也支持验证程序,但由于min_entries是{{1}} 0默认情况下你不需要任何。唯一的烦恼是你必须打开内部表格的数据(如果有的话)。

答案 1 :(得分:1)

如果有人来这里寻找解决方案,这里有一个简单的方法:

from wtforms.fields import FormField, _unset_value

class OptionalFormField(FormField):

    def process(self, formdata, data=_unset_value):
        self._formdata = formdata
        return super(OptionalFormField, self).process(formdata, data=data)

    def validate(self, form, extra_validators=tuple()):
        if extra_validators:
            raise TypeError('FormField does not accept in-line validators, as it gets errors from the enclosed form.')

        # Run normal validation only if there is data for this form
        for field_name in self._formdata.keys():
            if field_name.find(self.name) == 0:
                return self.form.validate()

        return True

这样做只会在表单数据中找到与该表单相关的键时才运行表单验证。

答案 2 :(得分:1)

感谢@aryeh OptionalFormField。我只是把我的略有改进(在我看来)版本放在这里:

class OptionalFormField(FormField):

    def process(self, formdata, *args, **kwargs):
        self._formdata = formdata
        return super(OptionalFormField, self).process(formdata, *args, **kwargs)

    def validate(self, *args, **kwargs):
        if self._formdata:
            for field_name in self._formdata.keys():
                if field_name.startswith(self.name + self.separator):
                    return super(OptionalFormField, self).validate(*args, **kwargs)
        return True