Django formset - 如何更新对象?

时间:2010-01-01 16:22:04

标签: django django-forms

如何使用request.POST

更新formset中的对象

这是我的代码,我的问题是这总是会创建一个新的PhoneNumber对象。但我想更新旧的PhoneNumber对象。

def contact_detail(request, contact_id):
    contact = get_object_or_404(Contact, pk=contact_id)
    phone_number_list = PhoneNumber.objects.filter(contact=contact_id)

    if request.method == 'POST':
        cform = ContactForm(request.POST, instance=contact)
        #the next line is probably wrong!
        phonenumberformset = PhoneNumberFormSet(request.POST, queryset=phone_number_list)

        if cform.is_valid() and phonenumberformset.is_valid():
            phonenumber_instances = phonenumberformset.save(commit=False)
            for phonenumber in phonenumber_instances:
                phonenumber.contact = contact
                phonenumber.save()

            request.user.message_set.create(message='The contact "%s" was chanced successfully.' % contact.__str__())
            return HttpResponseRedirect("/crm/contacts/?oby=1")
    else:
        cform = ContactForm(instance=contact)
        phonenumberformset = PhoneNumberFormSet(queryset=phone_number_list)

    return render_to_response(
        'crm/contact_detail.html',
        {'cform': cform, 'phonenumberformset': phonenumberformset,},
        context_instance = RequestContext(request),
    )

编辑:我创建了三个PhoneNumberForms:

PhoneNumberFormSet = modelformset_factory(PhoneNumber, max_num=3, extra=3, exclude=('contact',))

编辑:使用inlineformset_factory的解决方案:

@login_required
def contact_detail(request, contact_id):
    contact = get_object_or_404(Contact, pk=contact_id)
    PhoneNumberInlineFormSet = inlineformset_factory(Contact, PhoneNumber, max_num=3)

    if request.method == 'POST':
        cform = ContactForm(request.POST, instance=contact)
        classificationformset = ClassificationInlineFormSet(request.POST, request.FILES, instance=contact)
        addressformset = AddressInlineFormSet(request.POST, request.FILES, instance=contact)
        phonenumberformset = PhoneNumberInlineFormSet(request.POST, request.FILES, instance=contact)
        if cform.is_valid() and phonenumberformset.is_valid():
            contact = cform.save()
            phonenumberformset.save()

            request.user.message_set.create(message='The contact "%s" was chanced successfully.' % contact.__str__())
            return HttpResponseRedirect("/crm/contacts/?oby=1")
    else:
        cform = ContactForm(instance=contact)
        phonenumberformset = PhoneNumberInlineFormSet(instance=contact)

return render_to_response(
        'crm/contact_detail.html',
        {'cform': cform, 'phonenumberformset': phonenumberformset,},
        context_instance = RequestContext(request),)

这种方法甚至为每个内联表单添加了一个删除复选框。简单而且很棒。

1 个答案:

答案 0 :(得分:13)

使用modelformset_factory而不是inlineformset_factory使用instance - 请注意the documentation here - 抱歉,最初应该指出这一点。

然后您可以删除查询集内容,因为inlineformset_factory负责处理,并且只传递Contact参数(这里引用父模型,即{{1}对象)。您也不需要在保存时显式设置联系人属性,这也是需要处理的。