为Django中的formset中的每个表单赋值

时间:2013-04-15 17:28:32

标签: django forms dynamic formset

我正在尝试创建一个包含输入字段的formset。这将具有一些动态数量的元素,并且一旦提交表单,输入的文本将被指定为关联对象的“标签”。这可能听起来有些令人困惑,所以让我们看看我想要制作的表单类:

class TagsForm(forms.Form):

    tags = forms.CharField()
    def __init__(self, *args, **kwargs):
        applicantId = kwargs.pop('applicantId')

    def saveTags(self):
        applicant = Applicants.objects.get(id=applicantId)
        Tag.update(applicant,tags)

如您所见,我希望将表单传递给申请人的ID,然后在收到邮件请求后,通过调用每个表单saveTags更新该申请人对象的标签。以下是我处理此代码的代码:

    ...
    applicantQuery = allApplicantsQuery.filter(**kwargs)
    TagsFormSet = formset_factory(TagsForm)
    if request.method == 'POST':
        tags_formset = TagsFormSet(request.POST, request.FILES, prefix='tags')
        if tags_formset.is_valid()
            for tagForm in tags_formset:
                tagForm.saveTags()
    else:
        tags_formset = TagsFormSet(prefix='tags')
    ...

问题是我不知道如何使用applicantQuery查询集中的id创建初始表单集。理想情况下,我可以遍历查询集并将applicant.id发送到每个表单,但我不知道如何执行此操作。我也觉得我应该提到formset应该与申请人的申请人具有完全相同数量的表格。

1 个答案:

答案 0 :(得分:2)

您可以编写自定义表单集。

from django.forms.formsets import BaseFormSet

class TagFormSet(BaseFormSet):

    def __init__(self, *args, **kwargs):
        applicants = kwargs.pop('applicants')
        super(TagFormSet, self).__init__(*args, **kwargs)
        #after call to super, self.forms is populated with the forms

        #associating first form with first applicant, second form with second applicant and so on
        for index, form in enumerate(self.forms):
            form.applicant = applicants[index]

现在您不需要覆盖TagsForm的__init__

现在,您的每个表单都与申请人相关联。因此,您可以删除saveTags()的第一行。所以saveTags()成为:

def saveTags(self):
    #applicant was set on each form in the init of formset
    Tag.update(self.applicant, tags)

您的观看代码:

applicantQuery = allApplicantsQuery.filter(**kwargs)

#notice we will use our custom formset now
#also you need to provide `extra` keyword argument so that formset will contain as many forms as the number of applicants
TagsFormSet = formset_factory(TagsForm, formset=TagFormSet, extra=applicantQuery.count())

if request.method == 'POST':
    tags_formset = TagsFormSet(request.POST, request.FILES, prefix='tags', applicants=applicantQuery)
    if tags_formset.is_valid()
        for tagForm in tags_formset:
            tagForm.saveTags()
else:
    tags_formset = TagsFormSet(prefix='tags', applicants=applicantQuery)