In a django model custom save() method, how should you identify a new object?
I want to trigger a special action in the save() method of a Django model object when I'm saving a new record (not updating an existing record.)
Is the check for (self.id != None) necessary and sufficient to guarantee the self record is new and not being updated? Any special cases this might overlook?
Solution 1:
Alternative way to checking self.pk
we can check self._state
of the model
self._state.adding is True
creating
self._state.adding is False
updating
I got it from this page
Solution 2:
Updated: With the clarification that self._state
is not a private instance variable, but named that way to avoid conflicts, checking self._state.adding
is now the preferable way to check.
self.pk is None:
returns True within a new Model object, unless the object has a UUIDField
as its primary_key
.
The corner case you might have to worry about is whether there are uniqueness constraints on fields other than the id (e.g., secondary unique indexes on other fields). In that case, you could still have a new record in hand, but be unable to save it.
Solution 3:
Checking self.id
assumes that id
is the primary key for the model. A more generic way would be to use the pk shortcut.
is_new = self.pk is None
Solution 4:
The check for self.pk == None
is not sufficient to determine if the object is going to be inserted or updated in the database.
The Django O/RM features an especially nasty hack which is basically to check if there is something at the PK position and if so do an UPDATE, otherwise do an INSERT (this gets optimised to an INSERT if the PK is None).
The reason why it has to do this is because you are allowed to set the PK when an object is created. Although not common where you have a sequence column for the primary key, this doesn't hold for other types of primary key field.
If you really want to know you have to do what the O/RM does and look in the database.
Of course you have a specific case in your code and for that it is quite likely that self.pk == None
tells you all you need to know, but it is not a general solution.
Solution 5:
You could just connect to post_save signal which sends a "created" kwargs, if true, your object has been inserted.
http://docs.djangoproject.com/en/stable/ref/signals/#post-save