A lot of code checks if an object is saved as an update, or created with a check of the truthiness of instance.pk
, for example:
from django.db import models
class MyModel(models.Model):
# ...
def save(self, *args, **kwargs):
if self.pk:
print('updating')
else:
print('creating')
return super().save(*args, **kwargs)
Why is it a problem?
Because if the primary key field constructs a default value itself, self.pk
will contain that value, and therefore the check no longer works.
A popular example of this is when MyModel
has UUIDField
as primary key. For example:
from django.db import models
import uuid
class MyModel(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False
)
# …
If we now create an object without saving it in the database, it will already have a UUID:
>>> my_model = MyModel()
>>> my_model.id
UUID('c4e8412a-7ec0-419d-b34c-c0bafb67ff49')
so now the check will fail.
What can be done to resolve the problem?
We can work with instance._state.adding
instead, like:
from django.db import models
class MyModel(models.Model):
# …
def save(self, *args, **kwargs):
if self._state.adding:
print('creating')
else:
print('updating')
return super().save(*args, **kwargs)
This will determine how we got to this MyModel
object: from the database, or by creating a model object. This, however, does not say that a record with the primary key does not exist at the database level.
Indeed, MyModel(pk=1)._state.adding
will also be True
even if a record with id=1
already exists in the database. To confirm existence, the only option is to query the database.