How can I update an object from a formset using request.POST
?
Here is my code and my problem is that this always creates a new PhoneNumber
object. But I want to update the old PhoneNumber
object.
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),
)
Edit: I create three PhoneNumberForms:
PhoneNumberFormSet = modelformset_factory(PhoneNumber, max_num=3, extra=3, exclude=('contact',))
Edit: The solution using 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),)
This approach even adds a delete checkbox to each inline form. Easy and great.
Rather than use modelformset_factory
, use inlineformset_factory
- see the documentation here - sorry, should have pointed you to that initially.
Then you can drop the queryset stuff, since inlineformset_factory takes care of that, and just pass the instance
argument (which here refers to the parent model, ie the Contact
object). You also won't need to iterate through explicitly setting the contact attribute on save, as again that's taken care of.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With