我正在使用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
时返回inner
,errors
为空。
此代码不起作用:
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
?
答案 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