#sqlalchemy #wtforms #form-fields
Вопрос:
Итак, у меня есть эти формы wt:
ProfessionalAddress = FormField(AdressForm, default=lambda: ProfessionalAddress())
которая связывает подформу с моей основной формой. Чтобы убедиться, что подформа отображается, я добавил default
поведение, которое создает пустоту ProfessionalAddress
, если связь не существует.
Но проблема в том, что в некоторых случаях мне не нужна эта подформа, и она не отображается, поэтому поля не отправляются.
Но когда я звоню form = MainForm(formdata=request.form)
, так как поля не отправляются, form.ProfessionalAddress
устанавливается ProfessionalAddress()
значение, которое генерирует ошибку, так как моя база данных не допускает там пустых записей.
Я мог бы справиться с этим на уровне контроллера (что-то вроде if form.ProfessionalAddress is empty: form.ProfessionalAddress = None
), но это кажется банальным, и я бы предпочел разобраться с этим в Form
описании.
- Как я могу справиться с этим делом?
- Могу ли я отличить случай создания формы от случая заполнения формы?
- Или я могу заполнить значение по умолчанию позже (например. во время создания представления)?
- Или мой подход совершенно неверен?
Надеюсь, все ясно!
Спасибо
Ответ №1:
Один из способов сделать это-переопределить data
свойство поля формы, заставив его возвращать None
значения всех полей None
поля формы (или любой другой тест, который вы хотите применить).
class MyFormField(wtforms.FormField): @property def data(self): data = {name: f.data for name, f in self._fields.items()} if any(filter(lambda v: v is not None, data.values())): return data return None class MyForm(wtforms.Form): name = wtforms.StringField() professional_address = MyFormField(AddressForm, default=ProfessionalAddress())
если мы попробуем это сделать
form = MyForm(data={'name': 'Alice'}) for f in form:print(f) form = MyForm(formdata=MultiDict({'name': 'Alice'})) form.validate() print(form.data) form = MyForm(data={'name': 'Bob', 'professional_address': ProfessionalAddress(line1='1 High Street', line2='Dullsville')}) for f in form:print(f) form = MyForm(formdata=MultiDict([('name', 'Bob'), ('professional_address-line1', '1 High Street')])) form.validate() print(form.data)
мы видим, что форма отображается должным образом и None
возвращается, если поля профессионального адреса не заполнены.
lt;input id="name" name="name" type="text" value="Alice"gt; lt;table id="professional_address"gt;lt;trgt;lt;thgt;lt;label for="professional_address-line1"gt;Line1lt;/labelgt;lt;/thgt;lt;tdgt;lt;input id="professional_address-line1" name="professional_address-line1" required type="text" value=""gt;lt;/tdgt;lt;/trgt;lt;trgt;lt;thgt;lt;label for="professional_address-line2"gt;Line2lt;/labelgt;lt;/thgt;lt;tdgt;lt;input id="professional_address-line2" name="professional_address-line2" required type="text" value=""gt;lt;/tdgt;lt;/trgt;lt;/tablegt;
{'name': 'Alice', 'professional_address': None}
lt;input id="name" name="name" type="text" value="Bob"gt; lt;table id="professional_address"gt;lt;trgt;lt;thgt;lt;label for="professional_address-line1"gt;Line1lt;/labelgt;lt;/thgt;lt;tdgt;lt;input id="professional_address-line1" name="professional_address-line1" required type="text" value="1 High Street"gt;lt;/tdgt;lt;/trgt;lt;trgt;lt;thgt;lt;label for="professional_address-line2"gt;Line2lt;/labelgt;lt;/thgt;lt;tdgt;lt;input id="professional_address-line2" name="professional_address-line2" required type="text" value="Dullsville"gt;lt;/tdgt;lt;/trgt;lt;/tablegt;
{'name': 'Bob', 'professional_address': {'line1': '1 High Street', 'line2': None}}