Cómo obtener una comstackción de un formulario con elementos repetidos bien

El título realmente no lo dice, ya que tengo problemas para resumir el problema. Así que aquí va la larga explicación:

Digamos que estoy agregando información de contactos múltiples, y tengo estos campos:

  • Nombre del contacto
  • Método de contacto (correo electrónico, número de teléfono, mensaje instantáneo)
    • Si correo electrónico: muestra un campo de correo electrónico (digamos que este campo existe)
    • Si es un número de teléfono: muestra un campo de número de teléfono
    • Si mensaje instantáneo: muestra un campo de texto

Así que, de inmediato, voy a necesitar JavaScript para completar esto en la página en sí (para agregar campos de contacto para agregar o eliminar), con lo que estoy de acuerdo. Sin embargo, dado que puedo agregar múltiples contactos (y como desarrollador de software, no sé cuántos contactos quiere agregar el usuario, podría ser 1, 10 o 100)

Así que mi mayor problema es cómo voy a estructurar las cosas como los nombres para cada campo. ¿Debo arrojar todo en cosas como names[] , contactmethods[] y acceder a las cosas en orden, o si hay una mejor solución.

Además, si el servidor comienza a verificar esta información, y encuentra información mal formada, me gustaría poder enviar los datos que el cliente envió al servidor de vuelta al cliente, para que no pierdan todo lo que tienen ingresó. ¿Cómo lo lograría fácilmente?

Algunos antecedentes: Tecnologías actualmente en uso (eso es relevante):

  • Matraz
  • jQuery
  • WTForms

No es necesario construir nada (al menos en el lado del servidor): WTForms ya admite lo que necesita, los llama “recintos de campo” . El comportamiento que está buscando se encuentra en wtforms.fields.FormField y 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)) 

También necesitará un validador personalizado para validar el campo apropiado, dada la elección del usuario:

 # 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) 

Cuando llame a form.validate() en el lado del servidor, los campos se verificarán automáticamente con los requisitos y los errores se llenarán apropiadamente para que pueda procesarlos en el lado del cliente.

La creación de nuevos campos en el lado del cliente es simple y WTForms los recogerá en el back-end siempre y cuando usted nombre y use la misma convención de nomenclatura que utiliza , a saber, field.short_name + '-' + index .