2011-09-09 13 views
10

Tengo una página que muestra múltiples Formsets, cada uno de los cuales tiene un prefijo. Los conjuntos de formularios se crean utilizando formset_factory las opciones predeterminadas, incluido extra=1. Las filas se pueden agregar o eliminar con JavaScript.formset de Django: ¿muestra campos adicionales solo cuando no hay un conjunto de datos inicial?

Si el usuario agrega datos nuevos, aparece una fila en blanco. Perfecto.

Si el usuario ha agregado datos pero la validación del formulario ha fallado, en cuyo caso el formset se llena con datos POST usando MyFormset(data, prefix='o1-formsetname') etc., solo se muestran los datos que han ingresado. De nuevo, perfecto. (el o1 etc. se genera dinámicamente, cada o corresponde a una "opción", y cada "opción" puede tener múltiples conjuntos de formularios).

Sin embargo, si el usuario está editando los datos existentes, en cuyo caso el punto de vista rellena el juego de formularios utilizando MyFormset(initial=somedata, prefix='o1-formsetname') donde somedata es una lista de dicts de datos que provenían de un modelo en la base de datos, una línea en blanco adicional se inserta después de estos datos . No quiero que aparezca una fila en blanco a menos que el usuario agregue explícitamente uno usando JavaScript.

¿Hay alguna manera simple de evitar que el formset muestre una fila adicional si se establecen los datos iniciales? La razón por la que estoy usando initial en el tercer ejemplo es que si acabo de pasar los datos usando MyFormset(somedata, prefix='o1-formsetname') tendría que hacer un paso adicional de reformatear todos los datos en un dict de estilo POSTdata incluyendo prefijos para cada campo, por ejemplo o1-formsetname-1-price: x etc., así como el cálculo de los datos del formulario de gestión, que agrega una gran cantidad de complicaciones.

Una solución podría ser para interceptar el juego de formularios antes de que sea enviado a la plantilla y quitar manualmente la fila, pero el atributo extra_forms no parece tener permiso de escritura y el establecimiento de extra a 0 no hace ninguna diferencia. También podría hacer que JavaScript detecte este caso y elimine la fila. Sin embargo, no puedo evitar pensar que me estoy perdiendo algo obvio, ya que el comportamiento que quiero es lo que a mí me parece una conducta razonable.

Gracias.

+0

Estoy usando Django 1.1, donde el parámetro 'max_num' se comporta de manera diferente; ver la respuesta a continuación. – garybryan

Respuesta

3

He encontrado una solución que funciona con Django 1.1. Creé una subclase de BaseFormSet que anula el método total_form_count de modo que, si existen formularios iniciales, el total no incluye formularios adicionales. Quizás un truco, y quizás haya una mejor solución que no pude encontrar, pero funciona.

class SensibleFormset(BaseFormSet): 
    def total_form_count(self): 
     """Returns the total number of forms in this FormSet.""" 
     if self.data or self.files: 
      return self.management_form.cleaned_data[TOTAL_FORM_COUNT] 
     else: 
      if self.initial_form_count() > 0: 
       total_forms = self.initial_form_count() 
      else: 
       total_forms = self.initial_form_count() + self.extra 
      if total_forms > self.max_num > 0: 
       total_forms = self.max_num 
      return total_forms 
+0

Hago manualmente 'myFormset.extra = 1' dentro de' CreateView' y establezco el valor dentro de 'inlineformset_factory constructor' en 0. Creo que es menos código (una línea). –

5

utilizar el argumento max_num palabra clave para formset_factory:

MyFormset = formset_factory([...], extra=1, max_num=1) 

Para más detalles, echa un vistazo a limiting the maximum number of forms.

Un enganche: presumiblemente usted quiere proceso más de un formulario en blanco. Esto no es muy difícil; solo asegúrese de que no utilice utilice el argumento de palabra clave max_num en el lado de procesamiento POST.

+0

En realidad estaba viendo este problema nuevamente hoy. Esta solución no funciona como se esperaba: si hay varias filas iniciales, solo se muestra una de estas filas, ya que max_num las limita. Creo que esto es porque estoy en Django 1.1; el 1.1 dice "El parámetro max_num para formset_factory le da la capacidad de forzar la cantidad máxima de formularios que se mostrará en el formset", mientras que los 1.3 docs dicen "El parámetro max_num para formset_factory le da la capacidad de limitar el número máximo de formularios vacíos al formset se mostrará ", por lo que el significado de' max_num' ha cambiado. Alguna idea para 1.1? – garybryan

+0

¡Lo que se necesitaba para limitar el número de formularios a uno! simple y limpio ... ¡la mejor respuesta! – AmiNadimi

Cuestiones relacionadas