For a project I'm working on, in one of the models i am using models.UUIDField for primary key with the default value set to django.contrib.postgres.functions.RandomUUID
Here's my model.
from django.contrib.postgres.functions import RandomUUID
from django.db.models import JSONField
class NewsItem(models.Model):
id = models.UUIDField(primary_key=True, default=RandomUUID)
title = models.ForeignKey(RichText, models.DO_NOTHING, related_name='+',
null=True)
subtitle = models.ForeignKey(RichText, models.DO_NOTHING, related_name='+',
null=True)
excerpt = models.ForeignKey(RichText, models.DO_NOTHING, related_name='+',
null=True)
text = models.ForeignKey(RichText, models.DO_NOTHING, related_name='+',
null=True)
image = models.ForeignKey(ImageObject, models.DO_NOTHING, related_name='+',
null=True)
priority = models.IntegerField(null=True, default=0)
frequency = models.IntegerField(null=True, default=1)
text_effects = JSONField(blank=True, null=True, default=dict)
scroll_speed = models.IntegerField(null=True, default=1)
scroll_direction = models.IntegerField(null=True, default=0)
created_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
updated_at = models.DateTimeField(blank=True, null=True, auto_now=True)
class Meta:
managed = True
db_table = 'news_items'
The issue here is that i need to immediately access the primary key after the object has been inserted into the database, however trying to access pk or id after calling save simply returns a literal string RandomUUID()
In [1]: from media.models import NewsItem
In [2]: n = NewsItem()
In [3]: n.save()
In [4]: n.id
Out[4]: RandomUUID()
In [5]: str(n.id)
Out[5]: 'RandomUUID()'
However, if i issue a query like model.objects.first() or model.objects.last() and then access the id or pk of the returned instance, it works as expected.
In [6]: from media.models import NewsItem
In [7]: n = NewsItem.objects.first()
In [8]: n.id
Out[8]: UUID('9c485bd2-bb86-4aac-8d20-7cc85abec929')
In [9]: str(n.id)
Out[9]: '9c485bd2-bb86-4aac-8d20-7cc85abec929'
This cannot be used because there would be no guarantee that first or last returns the row i just inserted to the database. This led me to believe that perhaps all i need to do is a simply obj.refresh_from_db() call. However this throws a DoesNotExist exception.
In [12]: from media.models import NewsItem
In [13]: n = NewsItem()
In [14]: n.save()
In [15]: n.id
Out[15]: RandomUUID()
In [16]: n.refresh_from_db()
---------------------------------------------------------------------------
DoesNotExist Traceback (most recent call last)
<ipython-input-16-735aeb087dd1> in <module>
----> 1 n.refresh_from_db()
~/.var/envs/xkern/vdjango/lib/python3.9/site-packages/django/db/models/base.py in refresh_from_db(self, using, fields)
635 db_instance_qs = db_instance_qs.only(*fields)
636
--> 637 db_instance = db_instance_qs.get()
638 non_loaded_fields = db_instance.get_deferred_fields()
639 for field in self._meta.concrete_fields:
~/.var/envs/xkern/vdjango/lib/python3.9/site-packages/django/db/models/query.py in get(self, *args, **kwargs)
433 return clone._result_cache[0]
434 if not num:
--> 435 raise self.model.DoesNotExist(
436 "%s matching query does not exist." %
437 self.model._meta.object_name
DoesNotExist: NewsItem matching query does not exist.
In [17]:
So i went on to try other solutions like trying to explicitly call model.objects.get(pk=inserted_obj.id) or models.objects.filter(pk=inserted_obj.id)
This does not work either. Here is the issued query for for the latter.
In [21]: q = NewsItem.objects.filter(pk=n.id)
In [22]: print(q.query)
SELECT "news_items"."id", "news_items"."title_id", "news_items"."subtitle_id", "news_items"."excerpt_id", "news_items"."text_id", "news_items"."image_id", "news_items"."priority", "news_items"."frequency", "news_items"."text_effects", "news_items"."scroll_speed", "news_items"."scroll_direction", "news_items"."created_at", "news_items"."updated_at" FROM "news_items" WHERE "news_items"."id" = GEN_RANDOM_UUID()
In [23]:
That obviously would not work because that generates a new random uuid.
I'm not clear on how to proceed and i have hit a concrete wall at this point. Any ideas? Thanks.