2009-09-11 18 views
8

Mam kilka modeli i chcę wygenerować formularz wielokrotnego wyboru z tych danych. Tak więc formularz zawierałby pozycję dla każdej kategorii, a wybory byłyby umiejętnościami w tej kategorii.Automatyczne generowanie pól formularza dla formularza w 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) 

Czy istnieje sposób, aby automatycznie wygenerować pól formularza? Wiem, że mogę ręcznie dodać wpis "SkillCategory" w formularzu dla każdej kategorii SkillCategory, ale powodem, dla którego ma on być model, jest to, że umiejętności i kategorie umiejętności mogą być dowolnie edytowane.

chcę zrobić coś takiego: (próbowałem tego, ale nie zmusić go do pracy, nie pamiętam dokładnej błąd ...)

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

ROZWIĄZANIE

To tworzy wpis pola formularza przy użyciu Sk illCategory.name i przypisuje wybory, jak te w Skill. nazwa_pola/nazwa_ wyświetlana są używane w celu uniknięcia problemów z nie-ascii nazwami kategorii.

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) 

Odpowiedz

1

Spójrz na tworzenie dynamicznych formularzy w Django od b-list.org i uswaretech.com. Odniosłem sukces, używając tych przykładów do dynamicznego tworzenia treści formularzy z modeli.

+0

Dzięki, wskazał mi w dobrym kierunku, zobacz moją edycję powyżej dla mojego ostatecznego rozwiązania. – monkut

1

Co chcesz to formset. Otrzymasz zestaw wierszy, z których każdy mapuje do określonej umiejętności.

Zobacz stronę Formset documentation oraz stronę dotyczącą generowania formsets for models.

+0

Dzięki temu wydaje się to właściwym podejściem, po prostu muszę ponownie przemyśleć problem z tej perspektywy. – monkut

2

OK, więc nie można ustawiać takich pól na formularzach.Forma, z przyczyn, które staną się widoczne po zobaczeniu DeclarativeFieldsMetaclass, metaklas form.Form (ale nie form.BaseForm). Rozwiązanie, które może być przesadą w Twoim przypadku, ale przykład jak dynamiczna forma konstrukcji można zrobić, jest mniej więcej tak:

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, ale wygląda na wykonalne. Dzięki za referencję do kodu! – monkut

Powiązane problemy