2009-09-11 66 views
8

我有一些模型,我想從這些數據生成一個多選表單。 因此,表單將包含每個類別的條目,並且選擇將是該類別中的技能。自動生成表單域在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) 

是否有辦法來自動生成表單字段? 我知道我可以在表格中爲每個SkillCategory手動添加一個'SkillCategory'條目,但將其作爲模型的原因是技能和技能類別可以自由編輯。

我想要做這樣的事情: (這個我試過,但沒有得到它的工作,不記得確切的錯誤...)

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

這產生使用Sk的一個形式字段條目illCategory.name並將選項分配爲技能中的選項。 field_name/display_name用於避免與非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) 

回答

1

看看從b-list.orguswaretech.com創造Django的動態表單。我已經成功使用這些示例從模型動態創建表單內容。

+0

謝謝,這指出我在正確的方向,請參閱上面的編輯我的最終解決方案。 – monkut 2009-09-11 15:00:44

1

你想要的是一個表單集。這會給你一組行,每個行映射到一個特定的技能。

查看Formset documentation以及專門生成formsets for models的頁面。

+0

謝謝,這似乎是正確的做法,我只需要從這個角度重新考慮問題。 – monkut 2009-09-11 12:36:31

2

好吧,你不能在forms.Form上設置這樣的字段,原因是當你看到DeclarativeFieldsMetaclass時,form.Form的元類(但不是forms.BaseForm)的元類。這可能是矯枉過正,你的情況,但如何動態表單建設可以做一個例子的解決方案,是這樣的:

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

時髦,但看起來可行。感謝代碼參考! – monkut 2009-09-11 12:39:09