Как правильно построить форму с повторяющимися элементами

Название действительно не говорит об этом, так как у меня возникли проблемы с обобщением проблемы. Итак, вот длинное объяснение:

Допустим, я добавляю информацию о нескольких контактах, и у меня есть эти поля:

  • Имя контакта
  • Method of Contact (email, phone number, instant message)
    • If email: Show an email field (let's say this field exists)
    • Если номер телефона: показать поле номера телефона
    • Если мгновенное сообщение: Показать текстовое поле

Итак, сразу же мне понадобится JavaScript, чтобы завершить это на самой странице (чтобы добавить или удалить поля контактов), с чем я согласен. Однако, поскольку я могу добавить несколько контактов (и как разработчик программного обеспечения я не знаю, сколько контактов хочет добавить пользователь, это может быть 1, 10 или 100)

Итак, моя самая большая проблема заключается в том, как я собираюсь структурировать такие вещи, как имена для каждого поля. Должен ли я бросить все в такие вещи, как names[], contactmethods[] и получить доступ к вещам по порядку, или если есть лучшее решение.

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

Некоторая справочная информация: технологии, используемые в настоящее время (актуально):

  • Колба
  • jQuery
  • WTForms

person Pwnna    schedule 09.07.2012    source источник
comment
Flask позволяет вам действительно легко перебирать POST данные. Вы должны немного прочитать документацию и посмотреть, поможет ли это.   -  person Blender    schedule 10.07.2012
comment
Да, я знаком с этим. Моей главной заботой является возврат данных, если что-то испортилось.   -  person Pwnna    schedule 10.07.2012
comment
в соответствии с отправкой обратно всего, что получил сервер, чтобы клиент не потерял его, вы можете использовать флэш-сообщения (хорошо для одноразовой «отправки» от сервера к клиенту).   -  person darkphoenix    schedule 10.07.2012
comment
Однако флэш-сообщения не для форм... А также мне пришлось бы иметь очень сложный шаблон, так как он должен поддерживать несколько предварительно заполненных форм или начальный шаблон.   -  person Pwnna    schedule 10.07.2012
comment
возможно, тогда вам следует использовать массивы, хотя я давно не работал с массивами форм, и я не знаю, как с ними работать с помощью Flask.   -  person darkphoenix    schedule 10.07.2012
comment
Если вы не используете PHP, вам не нужен постфикс [] для обратной отправки нескольких значений — большинство веб-фреймворков позволяют получить доступ к нескольким значениям независимо от имени. Flask использует werkzeug.datastructures.MultiDict для хранения своих значений — если вы подозреваете, что будет возвращать несколько значений, просто вызовите request.form.your_field.getlist(), но также посмотрите мой ответ для альтернатив.   -  person Sean Vieira    schedule 10.07.2012


Ответы (1)


Не нужно ничего строить (по крайней мере, на стороне сервера) — WTForms уже поддерживает то, что вам нужно — он называет их "полевые ограждения". Поведение, которое вы ищете, находится в wtforms.fields.FormField и wtforms.fields.FieldList

class ContactForm(Form):
    name = TextField("Name", validators=[Required()])
    contact_type = SelectField("Contact Type",
                                validators=[Required()],
                                choices=[
                                    ("email", "Email"),
                                    ("phone", "Phone Number"),
                                    ("im", "Instant Message")
                                ])
    # `If` is a custom validator - see below
    email_address = TextField("Email",
                                  validators=[If("contact_type",
                                                     "email",
                                                     [Required(), Email()])
                                  ])
    phone_number = TextField("Phone #",
                                  validators=[If("contact_type",
                                                           "phone", [Required()])
                                  ])
    im_handle = TextField("IM Handle",
                                  validators=[If("contact_type",
                                                           "im", [Required()])
                                  ])


class SignUpForm(Form):
    # Other fields go here
    contacts = FieldList(FormField(ContactForm))

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

# CAUTION: Untested code ahead
class If(object):
    def __init__(self,
                      parent,
                      run_validation=None,
                      extra_validators=None,
                      msg=None):
        self.parent = parent
        self.msg = msg if msg is not None else u"Invalid"
        if callable(run_validation):
            self.run_validation = run_validation
        else:
            _run_validation = lambda self, parent, form: parent.data == run_validation
            self.run_validation = _run_validation
        self.extra_validators = extra_validators if extra_validators is not None \
                                                     else []

    def __call__(self, field, form):
        parent = getattr(form, self.parent)
        if self.run_validation(parent, form):
            return field.validate(form, extra_validators=self.extra_validators)

Когда вы вызываете form.validate() на стороне сервера, поля будут автоматически проверены на соответствие требованиям, а ошибки будут заполнены соответствующим образом, чтобы вы могли отобразить их обратно на стороне клиента.

Создать новые поля на стороне клиента очень просто, и WTForms подберет их на серверной части, если вы укажете используя то же соглашение об именах, что и, а именно field.short_name + '-' + index.

person Sean Vieira    schedule 10.07.2012
comment
Что, если у меня есть другое поле выбора, которое при некоторых параметрах превращало бы поле телефона, скажем, в 2 текстовых поля для анализа в кортеж или даже поле телефона в поле выбора? - person Pwnna; 15.07.2012