2009-09-11 5 views
8

Ich habe einige Modelle, und ich möchte ein Multi-Auswahlformular aus diesen Daten generieren. Also würde das Formular einen Eintrag für jede Kategorie enthalten und die Auswahl würde die Fähigkeiten in dieser Kategorie sein.Auto-Generieren von Formularfeldern für ein Formular in Django

models.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) 

Gibt es eine Möglichkeit zum automatischen erzeugen die Formularfelder? Ich weiß, dass ich manuell einen 'SkillCategory'-Eintrag im Formular für jede SkillCategory hinzufügen kann, aber der Grund dafür ist, dass Skills und Skillkategorien frei editiert werden können.

möchte ich so etwas wie dies zu tun: (Ich habe versucht, diese, aber nicht bekommen es funktioniert, nicht den genauen Fehler erinnern ...)

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

SOLUTION

das mit der Sk ein Formularfeld Eintrag erstellt illCategory.name und weist eine Auswahl wie in Skill zu. field_name/display_name werden verwendet, um Probleme mit nicht-ASCII Kategorienamen zu vermeiden.

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) 

Antwort

1

Werfen Sie einen Blick auf dynamische Formen in Django Erstellen von b-list.org und uswaretech.com. Mit diesen Beispielen konnte ich erfolgreich Formularinhalte aus Modellen erstellen.

+0

Danke, das hat mich in die richtige Richtung gelenkt, siehe oben meine Bearbeitung für meine endgültige Lösung. – monkut

1

Was Sie wollen, ist ein Formset. Dadurch erhalten Sie eine Reihe von Reihen, von denen jede einer bestimmten Fertigkeit zugeordnet ist.

Siehe die Formset documentation und die Seite speziell zum Generieren formsets for models.

+0

Danke, dies scheint der richtige Ansatz zu sein, ich muss das Problem nur aus dieser Perspektive überdenken. – monkut

2

Okay, so können Sie solche Felder nicht auf forms.Form setzen, aus Gründen, die offensichtlich werden, wenn Sie DeclarativeFieldsMetaclass sehen, die Metaklasse von forms.Form (aber nicht von forms.BaseForm). Eine Lösung, die in Ihrem Fall sein Overkill kann aber ein Beispiel dafür, wie dynamische Form Konstruktion durchgeführt werden kann, ist so etwas wie dieses:

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}) 
+0

Funky, aber sieht praktikabel aus. Danke für die Codenummer! – monkut

Verwandte Themen