WTForms-JSON с дополнительной вложенностью с использованием FormField

StackOverflow https://stackoverflow.com//questions/21032008

  •  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

Это означает, что проверка формы выполняется только в том случае, если в данных формы найдены ключи, относящиеся к этой форме.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top