2009-09-11 70 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