I have some models and I want to generate a multi-selection form from this data. So the form would contain an entry for each category and the choices would be the skills in that category.
我有一些模型,我想从这些数据生成一个多选形式。因此,表单将包含每个类别的条目,选择将是该类别中的技能。
models.py
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)
Is there a way to auto-generate the form fields? I know I can manually add a 'SkillCategory' entry in the form for each SkillCategory, but the reason to have it as a model is so skills and skillcategories can be edited freely.
有没有办法自动生成表单字段?我知道我可以在每个SkillCategory的表单中手动添加“SkillCategory”条目,但将其作为模型的原因是技能和技能类别可以*编辑。
I want to do something like this: (I tried this, but didn't get it to work, don't remember the exact error...)
我想做这样的事情:(我试过这个,但没有让它工作,不记得确切的错误...)
forms.py
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
解
This creates a form field entry using the SkillCategory.name and assigns choices as those in Skill. field_name/display_name are used to avoid issues with non-ascii category names.
这将使用SkillCategory.name创建表单字段条目,并将选项分配为Skill中的选项。 field_name / display_name用于避免非ascii类别名称的问题。
forms.py
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 个解决方案
#1
1
Take a look at creating dynamic forms in Django, from b-list.org and uswaretech.com. I've had success using these examples to dynamically create form content from models.
看看在Django中创建动态表单,从b-list.org和uswaretech.com。我已成功使用这些示例从模型动态创建表单内容。
#2
2
Okay so you can't set fields like that on forms.Form, for reasons which will become apparent when you see DeclarativeFieldsMetaclass, the metaclass of forms.Form (but not of forms.BaseForm). A solution which may be overkill in your case but an example of how dynamic form construction can be done, is something like this:
好的,所以你不能在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})
#3
1
What you want is a Formset. This will give you a set of rows, each of which maps to a specific Skill.
你想要的是一个Formset。这将为您提供一组行,每行都映射到特定的技能。
See the Formset documentation and the page specifically on generating formsets for models.
请参阅Formset文档和专门针对模型生成表单集的页面。
#1
1
Take a look at creating dynamic forms in Django, from b-list.org and uswaretech.com. I've had success using these examples to dynamically create form content from models.
看看在Django中创建动态表单,从b-list.org和uswaretech.com。我已成功使用这些示例从模型动态创建表单内容。
#2
2
Okay so you can't set fields like that on forms.Form, for reasons which will become apparent when you see DeclarativeFieldsMetaclass, the metaclass of forms.Form (but not of forms.BaseForm). A solution which may be overkill in your case but an example of how dynamic form construction can be done, is something like this:
好的,所以你不能在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})
#3
1
What you want is a Formset. This will give you a set of rows, each of which maps to a specific Skill.
你想要的是一个Formset。这将为您提供一组行,每行都映射到特定的技能。
See the Formset documentation and the page specifically on generating formsets for models.
请参阅Formset文档和专门针对模型生成表单集的页面。