¿Número variable de entradas con formas Django posibles?

¿Es posible tener un número variable de campos utilizando formularios django?

La aplicación específica es esta:

Un usuario puede cargar tantas fotos como desee en el formulario de carga de imágenes. Una vez que las imágenes se cargan, se llevan a una página donde pueden darles un nombre y una descripción. El número de imágenes dependerá de la cantidad que el usuario haya elegido para subir.

Entonces, ¿ cómo puedo hacer que django genere un formulario utilizando un número variable de campos de entrada (que podrían pasarse como un argumento si fuera necesario)?

edición: algunas cosas han cambiado desde que se escribió el artículo mencionado en la respuesta de jeff bauer .

Es decir, esta línea de código que parece no funcionar:

# BAD CODE DO NOT USE!!! return type('ContactForm', [forms.BaseForm], { 'base_fields': fields }) 

Así que aquí es lo que se me ocurrió …

La respuesta que utilicé:

 from tagging.forms import TagField from django import forms def make_tagPhotos_form(photoIdList): "Expects a LIST of photo objects (ie. photo_sharing.models.photo)" fields = {} for id in photoIdList: id = str(id) fields[id+'_name'] = forms.CharField() fields[id+'_tags'] = TagField() fields[id+'_description'] = forms.CharField(widget=forms.Textarea) return type('tagPhotos', (forms.BaseForm,), { 'base_fields': fields }) 

El etiquetado de notas no es parte de django, pero es gratuito y muy útil. échale un vistazo: django-tagging

Sí, es posible crear formularios dinámicamente en Django. Incluso puede mezclar y combinar campos dynamics con campos normales.

 class EligibilityForm(forms.Form): def __init__(self, *args, **kwargs): super(EligibilityForm, self).__init__(*args, **kwargs) # dynamic fields here ... self.fields['plan_id'] = CharField() # normal fields here ... date_requested = DateField() 

Para una mejor elaboración de esta técnica, vea el artículo de James Bennett: ¿Entonces desea una forma dinámica?

http://www.b-list.org/weblog/2008/nov/09/dynamic-forms/

Si tu corres

 python manage.py shell 

y escriba:

 from app.forms import PictureForm p = PictureForm() p.fields type(p.fields) 

verá que p.fields es un SortedDict. Solo tienes que insertar un nuevo campo. Algo como

 p.fields.insert(len(p.fields)-2, 'fieldname', Field()) 

En este caso se insertaría antes del último campo, un nuevo campo. Ahora debes adaptarte a tu código.

Otra alternativa es hacer un bucle para / mientras en tu plantilla y hacer el formulario en HTML, pero los formularios de django son una roca por alguna razón, ¿no?

Utilice cualquiera de los formularios múltiples (django.forms.Form no la etiqueta)

 class Foo(forms.Form): field = forms.Charfield() forms = [Foo(prefix=i) for i in xrange(x)] 

o agregue múltiples campos al formulario dinámicamente usando self.fields.

 class Bar(forms.Form): def __init__(self, fields, *args, **kwargs): super(Bar, self).__init__(*args, **kwargs) for i in xrange(fields): self.fields['my_field_%i' % i] = forms.Charfield()