LizzAlice
LizzAlice

Reputation: 720

At which point in UpdateView is the data saved?

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

Answers (3)

TeaPow
TeaPow

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

Alasdair
Alasdair

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

Sebastian Wozny
Sebastian Wozny

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

Related Questions