Editing a model instance using ModelForm creates a new instance instead of updating

I am trying to make a view that allows the user to edit an instance of a model (event in this case). Unfortunately, submitting this form creates a new instance (with a new identifier) ​​and does not even delete the old instance. I get the impression that the save method should update the instance in this case ...

NOTE. EventForm is ModelForm

I tried using force_update arg per https://docs.djangoproject.com/en/dev/ref/models/instances/#forcing-an-insert-or-update , but not a cube. I also tried just deleting the original event in the form.is_valid() block (by calling event.delete() ), but ... without a bone.

Do I have the feeling that the commit=False problem? I'm not sure!

Thanks.

(Please ignore the interval problems in the code snippet)

 def edit_event(request, event_id): event = Event.objects.get(pk=event_id) if request.method == 'POST': post_data = request.POST.copy() # here is some validation that can't be done in the ModelForm... #form = EventForm(post_data, request.FILES, instance=event) form = EventForm(post_data, request.FILES) if form.is_valid(): edited_event = form.save(commit=False) edited_event.save(force_update=True) # doesn't work with or without force_update arg #form.save_m2m() # needed for ManyToMany relationship return HttpResponseRedirect('/events/view/%s' % edited_event.id) else: form = EventForm(instance=event) return render_to_response('create_event.html', {'form': form,}, context_instance=RequestContext(request) ) 

UPDATE

I got rid of the M2M relationship on my model, so I can get rid of the line form.save_m2m() . This still does not work.

I also tried not to submit the instance when submitting the form, on the assumption that the correct fields will be pre-populated when the user submits (which is the case right now). This still does not work.

Am I missing an important detail when it comes to updating the model?

+4
source share
4 answers

From what I can understand, the problem with your code is that you always create a new instance before saving. Since you already got an instance of the event in "event = event.objects.get (pk = event_id)", you can just change that instance and save it, and I'm sure that this will cause django to do the update.

I suggest you check out this link: https://docs.djangoproject.com/en/dev/ref/models/instances/?from=olddocs#how-django-knows-to-update-vs-insert

This is a fairly simple explanation of the algorithm used by Django to distinguish between attachments and updates. If your object does not have its primary key (perhaps this is the "id" field that django automatically creates during synchronization), then it will be considered as a new object. If he has this field, then Django will try to find this particular record in the database, if it exists, it will be updated.

Hope the answer was clear enough.

+2
source

I think you should initialize the form as (as you already commented).

 form = EventForm(post_data, request.FILES, instance=event) 

Then the event object is associated with the form, and form.save() can perform the update instead of pasting.

+5
source

Work profile and updated work code:

 @login_required(login_url=LOGIN_URL) @csrf_exempt def profile(request): """ :param request: :param: :return: """ val = get_object_or_404(Profil, user=request.user) if request.method == 'POST': form = ProfilForm(request.POST, request.FILES, instance=val) if form.is_valid(): form.save() msg_ok = u'Profil updated' else: msg_err = u"Invalid form." else: form = ProfilForm(instance=val) return render(request, "back/profile.html", locals()) 
0
source

The example is too complex. Try starting from scratch with a simple model / view / form. Create a new model with one simple field, then create a model form and review and make sure that they work. Then start changing your view to bring it closer to its actual state.

-3
source

All Articles