es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

SQL Alchemy + WTForms FormField con valor predeterminado pero no insertar datos vacíos.

Tengo este wtform:

ProfessionalAddress = FormField(AdressForm, default=lambda: ProfessionalAddress())

que enlaza un subformulario con mi formulario principal. Para asegurarme de que el subformulario se muestra, agregué el comportamiento “default” que crea la dirección profesional vacía si la relación no existe.

Pero el problema es que en algunos casos no necesito este subformulario y no se muestra, por lo tanto, no se envía ningún campo.

Pero cuando llamo a form = MainForm(formdata=request.form), como no se envían campos, form.ProfessionalAddress se establece en ProfessionalAddress() lo que genera un error ya que mi base de datos no permite entradas vacías allí.

Podría manejarlo a nivel del controlador (algo como if form.ProfessionalAddress is empty: form.ProfessionalAddress = None), pero se siente como un truco y preferiría lidiar con esto en la descripción del Formulario.

¿Como puedo manejar esto?
¿Puedo diferenciar el caso de generación del caso de población del formulario?
¿O puedo poblar el valor predeterminado más tarde (por ejemplo, en el momento de generación de la vista)?
¿O mi enfoque es completamente incorrecto?

¡Espero que esté claro!

Gracias.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para manejar el caso donde el subformulario no es necesario, se puede hacer uso de un validador personalizado. Este validador solo validará el subformulario si tiene datos, y si no los tiene, lo ignorará y no asignará ningún valor a form.ProfessionalAddress. Aquí hay un ejemplo de cómo implementar este validador personalizado:

    from wtforms.validators import StopValidation
    
    class OptionalSubForm(object):
        def __init__(self, form_class):
            self.form_class = form_class
    
        def __call__(self, form, field):
            subform = self.form_class(formdata=formdata_prefix(field.name, form.data),
                                      prefix=field.name + '-')
            if not subform.validate():
                # esto detendrá la validación y no dará errores
                raise StopValidation()
            # si el subformulario es válido y tiene datos, asígnelo al campo
            if subform.data:
                field.data = subform.data
    

    Puede agregar este validador a su campo ProfessionalAddress de esta forma:

    ProfessionalAddress = FormField(AdressForm, default=lambda: ProfessionalAddress(), validators=[OptionalSubForm(AddressForm)])
    

    Esto solo asignará un valor a form.ProfessionalAddress si hay datos en el subformulario. Si no hay datos, lo ignorará y no asignará nada al campo.

    También se puede diferenciar el caso de generación de formulario del caso de población de formulario revisando si request.method es GET o POST, respectivamente. Se puede generar el valor predeterminado más tarde en el tiempo de generación de la vista asignando un nuevo valor predeterminado a ProfessionalAddress antes de renderizar el formulario, de esta forma:

    form.ProfessionalAddress = ProfessionalAddress()
    

    Esto asegurará que ProfessionalAddress no se establezca en un valor vacío cuando se quite el formulario.

    En general, su enfoque no está completamente equivocado, pero se puede mejorar utilizando un validador personalizado para manejar el caso donde el subformulario no es necesario, y asignando un nuevo valor predeterminado a ProfessionalAddress en el tiempo de generación de la vista para evitar establecerlo en un valor vacío.

Comments are closed.