Question

I am having a problem with my Django code inserting new rows instead of updating existing ones. Many people on here have asked for help with a similar problem, but generally they forget about setting instance as in form = SomeModelForm(request.POST or None, instance=some_model_instance). I seem to be doing that right, but it still doesn't save over existing data.

One other poster had the exact same issue (see Django form INSERTs when I want it to UPDATE). It looks like the code given to him to fix the problem resolved the issue, but no one explained why it worked when he asked!

VIEW

   if form_type == "edit_event":
        # we need to load all the data based on the event_id
        event_id = request.POST['event_id'] or None
        event_to_edit = mapDataManager.getEvent(event_id)
        if event_to_edit and mapDataManager.userCreatedEvent(request.user, event_to_edit):
            # this user actually created this event
            # let them edit it
            event_form = EventModelForm(request.POST or None, instance=event_to_edit)
            location_form = LocationModelForm(request.POST or None, instance=event_to_edit.location)
            list_of_event_scheds = EventSchedule.objects.filter(pk=event_id).values()
            event_sched_formset = EventScheduleModelFormSet(request.POST or None, initial=list_of_event_scheds)

            if event_form and location_form and event_sched_formset:
                if event_form.is_valid() and location_form.is_valid() and event_sched_formset.is_valid():
                    # update event
                    mapDataManager.updateEvent(event_form, location_form, event_sched_formset)
                    # redirect
                    return HttpResponseRedirect(reverse('map'))
                else:
                    # set feedback to show edit event form
                    feedback = "edit_event"

updateEvent()

def updateEvent(self, event_form, location_form, event_sched_forms):

    event = event_form.save(commit=False)
    location = location_form.save()
    event.location = location
    event.save()
    for event_sched_form in event_sched_forms: # loop through formset
        event_sched = event_sched_form.save(commit=False)
        event_sched.event = event
        event_sched.save()

Can anyone help me out? Am I missing something really basic?

EDIT: Just to clarify, NONE of my forms were updating, all were inserting. Based on Daniel's suggestion I think I need to use formsets to link all three modelforms that are being edited.

Was it helpful?

Solution 3

I was able to get the inline model formset working as per Daniel's suggestion with help from this blog post: http://charlesleifer.com/blog/djangos-inlineformsetfactory-and-you/

Just as an FYI, one crucial point I was missing is that the formset's instance refers to the parent model. Also, if you're displaying the formset manually in your template, don't forget to include {{ formset.id }}.

OTHER TIPS

For some strange reason, you're correctly passing instance to the main forms, but initial to EventScheduleModelFormSet, which is the immediate cause of the problem.

However, since these models obviously have a foreign key relationship, it sounds like you should be using a inline model formset:

from django.forms.models import inlineformset_factory
eventschedule_formset_class = inlineformset_factory(Event, EventSchedule)
event_sched_formset = eventschedule_formset_class(request.POST or None,
                                                  instance=event_to_edit)

Now there is no need for that updateEvent logic - you can just save event_sched_formset and it will correctly reference the event.

you are trying to save the EventScheduleModelFormSet form? there is no instance set only initial data so you are creating a new object every time. or am I missing something?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top