Generar automáticamente campos de formulario para un formulario en django

Tengo algunos modelos y quiero generar un formulario de selección múltiple a partir de estos datos. Así que el formulario contendría una entrada para cada categoría y las opciones serían las habilidades en esa categoría.

modelos.py

class SkillCategory(models.Model): name = models.CharField(max_length=50) class Skill(models.Model): name = models.CharField(max_length=50) category = models.ForeignKey(SkillCategory) 

¿Hay alguna manera de generar automáticamente los campos del formulario? Sé que puedo agregar manualmente una entrada de ‘Categoría de habilidad’ en el formulario para cada Categoría de habilidad, pero la razón para tenerlo como modelo es que las categorías de habilidades y habilidades se pueden editar libremente.

Quiero hacer algo como esto: (Lo intenté, pero no conseguí que funcionara, no recuerdo el error exacto …)

forms.py

 class SkillSelectionForm(forms.Form): def __init__(*args, **kwargs): super(SkillSelectionForm, self).__init__(*args, **kwargs) for c in SkillCategory.objects.all(): category_skills = [(pk, s.name) for s in c.skill_set.all()] setattr(self, c.name, forms.MultipleChoiceField(choices=category_skills, widget=forms.CheckboxSelectMultiple)) 

SOLUCIÓN

Esto crea una entrada de campo de formulario utilizando SkillCategory.name y asigna opciones como las de Skill. field_name / display_name se utilizan para evitar problemas con nombres de categorías que no son ascii.

forms.py

 def get_categorized_skills(): skills = {} for s in Skill.objects.values('pk', 'name', 'category__name').order_by('category__name'): if s['category__name'] not in skills.keys(): skills[s['category__name']] = [] skills[s['category__name']].append((s['pk'], s['name'])) return skills class SkillSelectionForm(forms.Form): def __init__(self, *args, **kwargs): super(SkillSelectionForm, self).__init__(*args, **kwargs) skills = get_categorized_skills() for idx, cat in enumerate(skills.keys()): field_name = u'category-{0}'.format(idx) display_name = cat self.fields[field_name] = forms.MultipleChoiceField(choices=skills[cat], widget=forms.CheckboxSelectMultiple, label=display_name) 

Eche un vistazo a la creación de formularios dynamics en Django, desde b-list.org y uswaretech.com . He tenido éxito usando estos ejemplos para crear dinámicamente contenido de formulario a partir de modelos.

De acuerdo, no puede configurar campos como ese en los formularios.Form, por razones que se harán evidentes cuando vea DeclarativeFieldsMetaclass , la metaclase de forms.Form (pero no de forms.BaseForm). Una solución que puede ser una exageración en su caso, pero un ejemplo de cómo se puede hacer la construcción de formas dinámicas, es algo como esto:

 base_fields = [ forms.MultipleChoiceField(choices=[ (pk, s.name) for s in c.skill_set.all() ]) for c in SkillCategory.objects.all() ] SkillSelectionForm = type('SkillSelectionForm', (forms.BaseForm,), {'base_fields': base_fields}) 

Lo que quieres es un Formset. Esto te dará un conjunto de filas, cada una de las cuales se asigna a una habilidad específica.

Consulte la documentación de Formset y la página específicamente sobre la generación de conjuntos de formularios para modelos .