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.