Having used integer primary keys for many projects, I've only recently switched over to using UUIDs on a few projects about a little less than a year ago. In the switch, an old solution I've often used for checking if an object exists, or is being created, has become obsolete.
A typical solution for checking if an object is being created in the
save method is usually to check if
None as such:
This isn't always true (see below)
class Parrot(UUIDModel): is_loud = models.BooleanField(default=True) ... def save(self, *args, **kwargs): if self.pk is None: do_some_stuff() super(Parrot, self).save(*args, **kwargs)
The issue with the above solution is that we are relying on a "hack" that utilizes Django's cached attributes, that checks to see if the primary key is
None. This will certainly fail if you're using UUIDs or any primary key that sets the
default parameter on the field.
import uuid class UUIDModel(models.Model): id = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4) ... class Meta: abstract = True
One solution would be to add a
createdtimestamp field to the model and check
if created is not Noneinstead. But this is potentially the same issue as above if a
defaultvalue is ever set on the
Another solution would be to perform a query to check if the object exists. Ex:
class Parrot(UUIDModel): is_loud = models.BooleanField(default=True) ... def save(self, *args, **kwargs): try: parrot = Parrot.objects.get(id=parrot.pk) except Parrot.DoesNotExist: parrot = None if parrot is None: do_some_stuff() super(Parrot, self).save(*args, **kwargs)
The downside with this solution is that you are now performing an extra query just to check if the object exists. But barring any possible race condition situations or
n+1 query scenario, this is probably your best bet for checking if the object exists.
If anyone else has a solution feel free to contact me, I'd love to hear your thoughts.