2010-03-01 31 views
18

Aquí es la forma en que lo estoy haciendo:¿Cómo harías un formset dinámico en Django?

{{ formset.management_form }} 
<table> 
    {% for form in formset.forms %} 
     {{ form }} 
    {% endfor %} 
</table> 
<a href="javascript:void(0)" id="add_form">Add Form</a> 

y aquí está la JS:

var form_count = {{formset.total_form_count}}; 
$('#add_form').click(function() { 
    form_count++; 
    var form = '{{formset.empty_form|escapejs}}'.replace(/__prefix__/g, form_count); 
    $('#forms').append(form) 
    $('#id_form-TOTAL_FORMS').val(form_count); 
}); 

Lo que me molesta específicamente es que tuve que escribir que escapejs etiqueta plantilla mí mismo. Simplemente elimina todas las líneas nuevas y escapa de cualquier comilla simple para que no estropee mi cadena. Pero, ¿qué esperaban exactamente los fabricantes de Django que hiciéramos en esta situación? ¿Y por qué tienen este campo oculto TOTAL_FORMS, cuando podrían haber usado una matriz como <input name="my_form_field[0]" /> y luego haber contado su longitud?

+1

¿Pero por qué estás mezclando plantilla de django y javascript? – Prashanth

+0

Para que pueda procesarlo. De lo contrario, tengo que escribir el manejo de formularios completamente personalizado en la vista también. Y Django parece alentar este método, es por eso * que proporcionaron este 'empty_form' con' __prefix__' para que puedas reemplazarlo, supuestamente. – mpen

+1

Me gusta el uso de '.empty_form' - bueno y corto. ¡Gracias! –

Respuesta

5

Hay algunos lugares en Django donde "el motivo" es porque así fue como se implementó para la aplicación de administración de Django, y creo que este es uno de ellos. Por lo tanto, la respuesta es que esperan que implementes tu propio javascript.

Consulte esta pregunta Dynamically adding a form... para obtener más ideas de JavaScript.

También hay dos aplicaciones conectables disponibles, django-dynamic-formset y django-dinamyc-form que no había visto hasta ahora cuando busco la primera.

+1

Escribir mi propio JS no es realmente un problema ... Solo tengo curiosidad de por qué solo nos dieron la mitad de las herramientas que necesitamos ... dicen que 'empty_form' puede ser utilizado para esto, sin embargo, se imprime con saltos de línea y tal que no es muy amigable para trabajar cuando intento meterlo en JS, a menos que esté malinterpretando algo. Creo que me gusta más mi método de formset dinámico ... Sospecho que le exige menos atención al cliente y requiere menos código :) Bueno ... supongo que solo estoy pizcando, pero todavía estoy muy en desacuerdo con mucho de las decisiones de diseño de Django. – mpen

+0

Bien, la decisión de diseño adecuada de Django es permanecer JS-framework neutral. El administrador es una aplicación contrib y, por lo tanto, técnicamente no forma parte del núcleo de Django, aunque algunas funcionalidades, como los conjuntos de formularios (aparentemente) provienen del trabajo en el administrador y, aunque creo que el administrador es una aplicación excelente, probablemente por falta de un gran diseño. –

+3

Los conjuntos de formularios son un gran dolor en el trasero si quieres hacer algo con ajax o agregar dinámicamente nuevos objetos. Con mucho, el mayor problema con Django al tratar de diseñar una aplicación tipo Web 2.0. Casi cambiamos a un framework Java después de haber invertido 6 meses en Django por esta misma razón, pero decidimos que habíamos pasado demasiado tiempo. –

4

Esta pregunta es un poco antigua, pero me tomó un tiempo darme cuenta de esto también.

Sugiero renderizar formset.empty_form en su plantilla como un campo oculto, y haciendo referencia a este campo en su javascript.

Aquí está un ejemplo complicado juego de formularios dinámicos desde el sitio de administración de Django: (pero tenga en cuenta que no se ha actualizado para utilizar empty_form ....)

[JS] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js

[plantilla HTML ] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html

+0

Hace poco (hace unas horas) rehice esto ... es realmente desagradable trabajar con ... tratar de agregar y eliminar formularios, y actualizar todos los ID dispersos, y asegurar que haya al menos un formulario, y validar todos ellos correctamente ... combínenlo con ajax/selección en cascada/selección contingente y se convierte en una pesadilla en miniatura. – mpen

+0

¿Trabajó fuera del ejemplo de django inlines.js? Lo modifiqué para mi sitio (quería los botones para agregar en una lista separada). No fue trivial (soy nuevo en js, por lo que me tomó un tiempo), pero creo que logré contener la mayor parte de la lógica en un único guión independiente. – bsk

1

es porque juego de formularios han sido creados para trabajar sin javascript, utilizando sólo el flujo de trabajo habitual HTTP.

Django es un agnóstico de Javascript.

Si desea agregar algo de javascript a la mezcla, puede usar el dedicated jquery plugin.

+1

Desearía poder ver una demostración, pero gracias. Django está diseñado para funcionar sin JavaScript, sí, pero parece tener algunos ganchos menores para crear JavaScript en ....Solo desearía que lo llevaran más lejos, porque es doloroso. – mpen

+0

@Mark: en realidad hay una demostración :-) Descargue el proyecto en http://code.google.com/p/django-dynamic-formset/ e incluya una demostración de django. –

+0

Eso no es lo que quise decir con una demostración. Quise decir sin tener que descargarlo ("demostración en vivo"?). Hay millones de proyectos y programas por ahí ... a las personas les gusta saber qué es lo que están obteniendo antes de invertir en el tiempo y esfuerzo y descargar y extraer cosas, y/o instalar/compilar. De todos modos, ya que * lo * recomendaron y no es solo algo aleatorio con lo que tropecé, lo verifico ... (si es una biblioteca tan maravillosa, esperarían que estuviera en uso en alguna parte que podría simplemente vincular a ...) – mpen

1

en mi caso. utilicé el complemento django-dynamic-formset (https://code.google.com/p/django-dynamic-formset/wiki/Usage)

y modifiqué la opción "agregado" y funcionó bien.

 $('#formset-table tbody tr').formset({ 
      prefix: '{{ formset.prefix }}', 
      formCssClass: '{{ formset.prefix }}-inlineformset', 
      added: function(obj_tr){ 
   var form = $(obj_tr).html().replace(/\-(\w+)\-(\w+)(fix__)\-/g, '-'); 
       $(obj_tr).html(form); 

      }, 

esta expresión regular reemplazar la cadena [prefijo] - prefijo pares '-'

tal vez no es la mejor solución, pero funcionó.

1

Existen algunos casos de posible XSS cuando se usa formset.empty_form como una cadena, reemplazando '__prefix__' al índice de formulario de formset real. Mi aplicación conectable convierte formset.empty_form en la plantilla Knockout.js que luego se clona a través de enlaces personalizados Knockout.js. Además, Knockout.js vuelve a calcular automáticamente los índices de identificación de campo de formulario, cuando el formulario de formset recién agregado se elimina dinámicamente antes de enviar el formulario completo con los formularios en línea. Aquí está la documentación:

https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#dynamically-adding-new-related-formset-forms

Knockout.js vinculante también evita XSS al cargar los campos personalizados en línea con Javascript.

Cuestiones relacionadas