python - validators - wtforms
Validar el formulario WTForm en función del botón presionado (1)
En mi formulario, tengo dos botones que utilizo para enviar el formulario. Un botón borra los archivos seleccionados (presentados en una tabla, una casilla de verificación en un objeto) y el otro los selecciona para procesarlos.
Cuando los archivos se seleccionan al eliminarse, no es necesaria la validación (más allá de verificar que se haya seleccionado al menos un archivo). Sin embargo, para el procesamiento, necesito asegurarme de que haya exactamente un archivo de cierta extensión. Básicamente, necesito diferentes procesos de validación basados en el botón en el que el usuario hizo clic.
¿Cómo puedo hacer esto mejor? Sé que puedo realizar la validación en la vista, pero preferiría validar esto dentro del formulario, ya que es más limpio.
Aquí están los formularios en cuestión:
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
La clave a tener en cuenta sobre los botones en HTML es que solo el botón que se presiona envía sus datos de vuelta al servidor. De modo que puede verificar si el campo de data
del botón está configurado usando if form.process_button.data
y las cosas funcionarán en el caso general.
En su caso particular, dado que ambos botones extraen sus datos del mismo nombre de parámetro subyacente ( action
), deberá verificar que los datos en uno de los campos de sus botones sean los esperados:
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