Ответ 1
Взгляните на создание динамических форм в Django, от b-list.org и uswaretech.com. Я успешно использовал эти примеры для динамического создания содержимого формы из моделей.
У меня есть несколько моделей, и я хочу создать из этих данных многоэкранную форму. Таким образом, форма будет содержать запись для каждой категории, и выбор будет навыками в этой категории.
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 используются, чтобы избежать проблем с именами категорий non-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)
Взгляните на создание динамических форм в Django, от b-list.org и uswaretech.com. Я успешно использовал эти примеры для динамического создания содержимого формы из моделей.
Хорошо, поэтому вы не можете устанавливать такие поля в формах. Форм, по причинам, которые станут очевидными, когда вы увидите DeclarativeFieldsMetaclass, metaclass of forms.Form(но не формы .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})
То, что вы хотите, это Formset. Это даст вам набор строк, каждый из которых соответствует определенному навыку.
См. Документация по формату и страница специально для генерации formsets для моделей.