在django中为表单自动生成表单字段

时间:2009-09-11 05:51:27

标签: python django django-forms

我有一些模型,我想从这些数据生成多选表格。 因此,表单将包含每个类别的条目,选择将是该类别中的技能。

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

解决方案

这将使用SkillCategory.name创建表单字段条目,并将选项分配为Skill中的选项。 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)

3 个答案:

答案 0 :(得分: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})

答案 1 :(得分:1)

你想要的是一个Formset。这将为您提供一组行,每行都映射到特定的技能。

请参阅Formset documentation以及有关生成formsets for models的具体页面。

答案 2 :(得分:1)

b-list.orguswaretech.com开始,在Django中创建动态表单。我已成功使用这些示例从模型中动态创建表单内容。