WTForms-JSON с дополнительной вложенностью с использованием FormField
-
21-12-2019 - |
Вопрос
я использую WTForms-JSON и обработка вложенных форм.Я хотел бы сделать внутреннюю форму необязательной, но если внутренняя форма присутствует, я бы хотел, чтобы ее поля были обязательными.Проблема, с которой я столкнулся, заключается в том, что FormField
не принимает валидаторов.
(Хотя я использую WTForms-JSON, я считаю, что это применимо и к стандартным 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
настоящее?
Решение
Самый простой способ — обернуть FormField
в FieldList
, с max_entries
установить на 1. FieldList
также поддерживает валидаторы, но поскольку min_entries
по умолчанию равен 0, вам он не нужен.Единственным неудобством будет то, что вам придется развернуть данные внутренней формы, если они доступны.
Другие советы
Спасибо @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
Если кто-то придет сюда в поисках решения этой проблемы, вот простой вариант:
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
Это означает, что проверка формы выполняется только в том случае, если в данных формы найдены ключи, относящиеся к этой форме.