Рубрики
Без рубрики

Объединение нескольких форм в Flask-wtforms, но независимо от проверки

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

У нас есть проект Flask, который появится в Белый октябрь который будет включать форму профиля пользователя. Эта форма может рассматриваться как одна большая форма или как несколько меньших форм, а также может быть отправлена в целом или в разделе.

В рамках планирования этой работы мы сделали подтверждение концепции объединения нескольких подчинений в Flask-WTForms и их проверки.

Обратите внимание, что это немного другой шаблон для «вложенных форм». Вложенные формы часто используются для динамических повторяющихся элементов – например, добавление нескольких адресов в профиль с использованием одной вложенной формы адреса. Но наш случай использования был несколькими формами, объединенными вместе не динамическим способом и потенциально обрабатываемым независимо. Эта статья также не учитывает ситуацию с несколькими Отдельный HTML формируется на одной странице.

Этот документ объясняет ключевые вещи, которые вам нужно знать, чтобы объединить формы вместе в Flask-WTF, независимо от того, используете ли вы Ajax или простой возврат.

Первое, что нужно знать, это то, как объединить несколько форм WTFForms в одну. Для этого используйте Formfield Тип поля (он же «корпус»). Вот пример:

from flask_wtf import FlaskForm
import wtforms

class AboutYouForm(FlaskForm):
    first_name = wtforms.StringField(
        label="First name", validators=[wtforms.validators.DataRequired()]
    )
    last_name = wtforms.StringField(label="Last name")

class ContactDetailsForm(FlaskForm):
    address_1 = wtforms.StringField(
        label="Address 1", validators=[wtforms.validators.DataRequired()]
    )
    address_2 = wtforms.StringField(label="Address 2")

class GiantForm(FlaskForm):
    about_you = wtforms.FormField(AboutYouForm)
    contact_details = wtforms.FormField(ContactDetailsForm)

Как видите, третья форма здесь сделана путем объединения первых двух.

Вы можете отображать эти подчинки так же, как и в любом другом поле формы:

{{ form.about_you }}

(Рендеринг формы обсуждается более подробно ниже.)

Как только мы объединили наши формы, второе, что мы хотели доказать, это то, что они могут быть подтверждены независимо.

Обычно вы подтверждаете (целую) форму, как это:

if form.validate_on_submit()
    # do something

( validate_on_submit возвращает true, если форма была отправлена и действительна.)

Оказывается, вы можете довольно легко проверить поле индивидуального формы. Для нашего able_you Поле (которая является подразделением), это просто выглядит так:

form.about_you.validate(form)

Определение того, что подтвердить

Мы добавили несколько кнопок отправки в форму, чтобы можно было обработать либо отдельные подчинки, либо все. Если вы даете кнопки отправки разные имена, вы можете легко проверить, какой из них нажимали, проверяли и сохранили соответствующим образом (убедитесь, что вы сохраняете только данные, которые вы подтверждены):



А потом:

if "submit-about-you" in request.form and form.about_you.validate(form):
    # save About You data here
elif "submit-whole-form" in request.form and form.validate():
    # save all data here

Если у вас есть один метод маршрута, обрабатывающий как http get, так и для публикации методов, нет необходимости явно проверять, является ли это обратной связью перед выполнением вышеуказанных проверок – ни одна кнопка не будет в request.form Если это не пост.

Альтернативные подходы

В качестве альтернативы вы можете дать обе кнопки отправки одинакового имени и дифференцировать значение. Тем не менее, это означает, что изменения в формулировке, связанной с пользователем, на ваших кнопках (как это их свойство стоимости) могут нарушить предприятия IF в вашем коде, что не идеально, поэтому разные имена являются нашим рекомендуемым подходом.

Если вы хотите включить свои кнопки отправки в сами классы форм WTForms, а не жестко кодируя HTML, вы можете проверить, какой из них был представлен, проверив соответствующее поле данные свойство – см. Здесь Для небольшого проработанного примера этого.

Gotcha: проверка на основе браузера и несколько кнопок отправки

Есть одна закуска, которую вы нажмете, если используете несколько кнопок для отправки для проверки/сохранения данных только от одной подраздела более крупной формы.

Если у вашей формы есть Требуется Набор свойств (что будет делать WTForms, если вы используете, например, валидатор все Требуемые поля заполнены-не знает, что вас обеспокоены только частью формы (поскольку эта частичная подача реализована на стороне сервера).

Поэтому, предполагая, что вы хотите продолжать использовать Требуется Свойство (которое вы должны), вам нужно добавить немного JavaScript, чтобы динамически изменить свойства поля формы при представлении.

Это не проблема, если вы используете AJAX, а не возвраты для подачи заявок; Смотрите ниже, как это сделать.

Примеры в этом разделе используют явные имена поля. На практике вы захотите создать Полевой макрос На что вы можете передать каждое поле формы, а не повторять этот код для каждого поля формы, которое у вас есть. Эта ссылка также показывает, как отображать этикетку и виджет поля отдельно, что дает вам больше контроля над вашей наценкой.

Как упомянуто выше, подчинки могут быть отображены с помощью одной линии, как и в любом другом поле:

{{ form.about_you }}

Если вы хотите отображать поля из своих подразформных форм в отдельности, это будет выглядеть примерно так:


{{ form.about_you.first_name }}

Как вы видите, вы не можете выполнять однострочный рендеринг полей форм и их метки для отдельных полей в подчинках – вы должны явно отобразить этикетку.

Отображение ошибок субперформирования

Для нормального поля формы вы можете отображать связанные ошибки, итерация над Ошибки Собственность как это:

{% if form.your_field_name.errors %}
    
    {% for error in field.errors %}
  • {{ error }}
  • {% endfor %}
{% endif %}

В этом случае Ошибки это просто список строк ошибок для поля.

Однако для подчинения, в которой вы используете тип поля Formfield, однако, Ошибки это Словарь Сопоставление имен поля с списками ошибок. Например:

{
    'first_name': ['This field is required.'],
    'last_name': ['This field is required.'],
}

Следовательно, итерация над этим в вашем шаблоне сложнее. Вот пример, который отображает ошибки для всех полей в подразделении (обратите внимание на использование элементов

{% if form.about_you.errors %}
    
    {% for error_field, errors in form.about_you.errors.items() %}
  • {{ error_field }}: {{ errors|join(', ') }}
  • {% endfor %}
{% endif %}

До сих пор мы рассмотрели случай проверки подчинений, когда данные отправляются через полностраничный отправку. Тем не менее, вы, скорее всего, захотите выполнить проверку подформ, используя AJAX, асинхронно публикуя данные формы обратно в приложение Flask с помощью JavaScript.

Уже есть отличная статья Энтони Планкетта под названием « Размещение WTFORM через AJAX с колкой “, который содержит почти все, что вам нужно знать, чтобы сделать это.

В этой статье, поэтому я просто закончу, уточнив одну проблему, которую у вас возникнет, если вы сделаете это с несколькими кнопками отправки – определение нажатой кнопки отправки

Определение кнопки отправки нажатый

При публикации данных обратно на сервер с JavaScript вы, вероятно, будете использовать такой метод, как JQuery’s serialize Анкет Тем не менее, данные, созданные этим методом, не включают подробную информацию о кнопке, нажатой, чтобы отправить форму.

Есть Различные способы Вы можете обойти это ограничение. Подход, который я нашел наиболее полезным, заключался в том, чтобы динамически добавить скрытое поле в форму с тем же именем и значением, что и кнопка отправки (см. здесь ). Таким образом, код Python, как Если "отправить-about-you" в request.form (См. Выше) может оставаться неизменным, независимо от того, используете ли вы Ajax или Repacks.

Оригинал: “https://dev.to/sampart/combining-multiple-forms-in-flask-wtforms-but-validating-independently-cbm”