Проверить форму WTForm на основе нажатой кнопки

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

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

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

Вот формы, о которых идет речь:

class ButtonWidget(object):
    """A widget to conveniently display buttons.
    """
    def __call__(self, field, **kwargs):
        if field.name is not None:
            kwargs.setdefault('name', field.name)
        if field.value is not None:
            kwargs.setdefault('value', field.value)
        kwargs.setdefault('type', "submit")
        return HTMLString('<button %s>%s</button>' % (
            html_params(**kwargs),
            escape(field._value())
            ))

class ButtonField(Field):
    """A field to conveniently use buttons in flask forms.
    """
    widget = ButtonWidget()

    def __init__(self, text=None, name=None, value=None, **kwargs):
        super(ButtonField, self).__init__(**kwargs)
        self.text = text
        self.value = value
        if name is not None:
            self.name = name

    def _value(self):
        return str(self.text)

class MultiCheckboxField(SelectMultipleField):
    """
    A multiple-select, except displays a list of checkboxes.

    Iterating the field will produce subfields, allowing custom rendering of
    the enclosed checkbox fields.
    """
    widget = ListWidget(prefix_label=False)
    option_widget = CheckboxInput()

class ProcessForm(Form, HiddenSubmitted):
    """
    Allows the user to select which objects should be
    processed/deleted/whatever.
    """

    PROCESS = "0"
    DELETE = "-1"

    files = MultiCheckboxField("Select", coerce=int, validators=[
        Required()
        ]) # This is the list of the files available for selection
    process_button = ButtonField("Process", name="action", value=PROCESS)
    delete_button = ButtonField("Delete",  name="action", value=DELETE)

    def validate_files(form, field):
        # How do I check which button was clicked here?
        pass

person Plasma    schedule 25.04.2014    source источник


Ответы (1)


Ключевым моментом, который следует отметить о кнопках в HTML, является то, что только нажатая кнопка отправляет свои данные обратно на сервер. Таким образом, вы можете просто проверить, установлено ли поле data кнопки с помощью if form.process_button.data, и в общем случае все будет работать.

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

def validate_files(form, field):
    # If the ButtonFields used different names then this would just be
    # if form.process_button.data:
    if form.process_button.data == ProcessForm.PROCESS:
        # Then the user clicked process_button
    else:
        # The user clicked delete_button
person Sean Vieira    schedule 25.04.2014
comment
Вы, кажется, не совсем правы. Что мне кажется, так это то, что поле data для обеих кнопок установлено в указанное поле data нажатой кнопки. Тем не менее, это позволяет мне увидеть, какая кнопка отмечена, так что спасибо. Если вы отредактируете свой ответ, я отмечу, что вы правы: P - person Plasma; 25.04.2014
comment
@Plasma - я упустил тот факт, что вы дали обеим кнопкам одно и то же имя (name="action"). По умолчанию у них будет два разных имени (process_button и delete_button), поэтому при отправке будет установлено только одно. - person Sean Vieira; 25.04.2014