[英]WTForms-JSON with optional nesting using FormField
I'm using WTForms-JSON and processing nested forms. 我正在使用WTForms-JSON并处理嵌套表单。 I'd like to make an inner form optional, but if the inner form is present, I'd like its fields to be required.
我想使内部表单可选,但如果内部表单存在,我希望它的字段是必需的。 The problem I'm running into is that
FormField
doesn't accept validators. 我
FormField
的问题是FormField
不接受验证器。
(Although I'm using WTForms-JSON, I believe this applies to vanilla WTForms as well.) (虽然我使用的是WTForms-JSON,但我相信这也适用于vanilla WTForms。)
This code works but doesn't behave the way I want: 此代码有效,但不按我想要的方式运行:
class InnerForm(Form):
foo_id = IntegerField("Foo ID", [Required()])
class OuterForm(Form):
inner = FormField(InnerForm)
The problem with the above code is that inner
is implicitly required. 上面代码的问题是
inner
隐是隐式需要的。 Oddly, while validate()
returns False
when inner
is omitted, errors
is empty. 奇怪的是,当省略
inner
时, validate()
返回False
, errors
为空。
This code doesn't doesn't work: 此代码不起作用:
class InnerForm(Form):
foo_id = IntegerField("Foo ID", [Required()])
class OuterForm(Form):
inner = FormField(InnerForm, "Inner", [Optional()])
The latter produces this error: 后者产生此错误:
TypeError: FormField does not accept any validators. Instead, define them on the enclosed form.
My question is: how can I make inner
optional, but require foo_id
if inner
is present? 我的问题是:如何使
inner
可选,但如果inner
存在则需要foo_id
?
The easiest way is to wrap the FormField
in a FieldList
, with max_entries
set to 1. FieldList
also supports validators, but since min_entries
is 0 by default you should not need any. 最简单的方法是将
FormField
包装在FieldList
,并将max_entries
设置为1. FieldList
也支持验证器,但由于min_entries
默认为0,因此您不需要任何验证器。 The only annoyance will be that you will have to unwrap the inner form's data if it is available. 唯一的烦恼是,如果内部表格的数据可用,您必须打开它。
In case anyone comes here looking for a solution to this, here is a simple one: 如果有人来这里寻找解决方案,这里有一个简单的方法:
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
What this does is it only runs the form validation if it finds keys in the formdata that pertain to that form. 这样做只是在它找到与该表单相关的formdata中的键时才运行表单验证。
Thanks @aryeh for OptionalFormField
. 感谢@aryeh for
OptionalFormField
。 I just put here my slightly improved (in my opinion) version: 我只是把我的略有改进(在我看来)版本放在这里:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.