Автоматически генерировать поля формы для формы в Django - PullRequest
8 голосов
/ 11 сентября 2009

У меня есть несколько моделей, и я хочу сгенерировать форму множественного выбора на основе этих данных. Таким образом, форма будет содержать запись для каждой категории, а в качестве выбора будут использоваться навыки в этой категории.

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 ]

2 голосов
/ 11 сентября 2009

Хорошо, поэтому вы не можете устанавливать такие поля в формах. По причинам, которые станут очевидны, когда вы увидите DeclarativeFieldsMetaclass , метакласс форм.Form (но не форм. BaseFase). Решение, которое может оказаться излишним в вашем случае, но пример того, как можно построить динамическое построение формы, выглядит примерно так:

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 голос
/ 11 сентября 2009

Посмотрите на создание динамических форм в Django с b-list.org и uswaretech.com Я успешно использовал эти примеры для динамического создания содержимого форм из моделей.

1 голос
/ 11 сентября 2009

То, что вы хотите, это Formset. Это даст вам набор строк, каждая из которых соответствует определенному навыку.

См. Документацию Formset и страницу, посвященную созданию наборов форм для моделей .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...