Reputation: 720
I was wondering when the data given to an UpdateView
was saved.
I have the following situation: I update a model object via a form. I would expect the changes to the model only to be saved after the UpdateView
's form_valid
is through. But when I print the object attributes right at the start of form_valid
, they have already changed to the new ones inserted into the form.
So when exactly is the change to the model saved and how would I go about if I wanted to do something with the previous values?
I am relatively new to Django and I hope that this question is not too far off track.
Upvotes: 8
Views: 2269
Reputation: 677
The default implementation of UpdateView.form_valid
is as follows (straight from Django):
def form_valid(self, form):
"""
If the form is valid, save the associated model.
"""
self.object = form.save()
return super(ModelFormMixin, self).form_valid(form)
If you wanted to access the "old" instance within form_valid
you could do the following:
def form_valid(self, form):
updated_instance = form.save(commit=False)
original_instance = MyModel.objects.get(pk=updated.pk)
# Do what ever you want with these two instances.
# ...
# The form is saved in the super call below, hence the
# commit=False above.
return super(self, MyView).form_valid(form)
Upvotes: 2
Reputation: 308839
The object is not saved to the database until form.save()
is called in form_valid()
method. If you override the method and save with instance = form.save(commit=False)
, it is not saved to the database until you call instance.save()
.
However, when form.is_valid()
is called in the post()
method, this immediately updates self.object
with the new values. Therefore, if you access self.object in the form_valid()
method, it already has the new values.
You could refetch the original object from the database:
original_object = MyModel.objects.get(pk=self.object.pk)
If you just want to know which fields changed, form.changed_data
might be enough for you.
Upvotes: 4
Reputation: 17506
The objects received in form_valid
are those of the yet unsaved object, not of the object retrieved from the database.
Try
newobject = Mymodel.objects.get(pk=object.pk)
To verify that the object retrieved this way from the database still has the old attributes.
Note: This will not work on CreateView
because objects in CreateView
don't exist in the database yet and therefore do not have a PK yet.
The actual work of saving the updated object is done in ModelFormMixin
line 123, one of the Mixin Classes of UpdateView
. From the Source Code:
def form_valid(self, form):
"""If the form is valid, save the associated model."""
self.object = form.save()
return super().form_valid(form)
Upvotes: 5