【问题标题】:Django formset - how to update an object?Django formset - 如何更新对象?
【发布时间】:2010-01-01 16:22:03
【问题描述】:

如何使用request.POST 从表单集中更新对象?

这是我的代码,我的问题是这总是会创建一个新的 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),)

这种方法甚至为每个内联表单添加了一个删除复选框。简单又好用。

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    不要使用modelformset_factory,而是使用inlineformset_factory - 请参阅the documentation here - 抱歉,最初应该向您指出这一点。

    然后你可以删除查询集的东西,因为 inlineformset_factory 会处理这些,只需传递instance 参数(这里指的是父模型,即Contact 对象)。您也不需要在保存时通过显式设置联系人属性进行迭代,因为这又得到了照顾。

    【讨论】:

    • 谢谢..我今天学到了很多 :) 这种方法也遇到了另一个错误:IndexError at /crm/contacts/15/ - list index out of range .. 希望我能摆脱它使用 inlineformset_factory
    • 好吧似乎工作。我刚刚尝试了 PhoneNumber 对象。哇..我为每个内联对象都有一个非常好的删除复选框.. wuhaa :) 但是有一个问题:有没有办法定义一个 max_num 的内联对象?因为它总是增加三个内联。
    • 嗯,好的,与“普通”表单集相同的解决方案。 max_num=3 或 extra=0
    猜你喜欢
    • 1970-01-01
    • 2020-04-24
    • 2018-06-05
    • 2023-03-08
    • 2020-07-07
    • 2019-07-21
    • 2011-05-05
    • 1970-01-01
    • 2020-05-08
    相关资源
    最近更新 更多