Django ORM - Первичный ключ недоступен после сохранения при использовании UUIDField и RandomUUID в Postgres

Для проекта, над которым я работаю, в одной из моделей я использую models.UUIDField для первичного ключа со значением по умолчанию django.contrib.postgres.functions.RandomUUID

Вот моя модель.

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'

Проблема в том, что мне нужно немедленно получить доступ к первичному ключу после того, как объект был вставлен в базу данных, однако попытка получить доступ к pk или id после вызова save просто возвращает литеральную строку 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()'

Однако, если я выдаю запрос типа model.objects.first() или model.objects.last(), а затем обращаюсь к id или pk возвращенного экземпляра, все работает, как ожидалось.

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'

Это не может быть использовано, поскольку нет гарантии, что first или last вернет в базу данных строку, которую я только что вставил. Это навело меня на мысль, что, возможно, все, что мне нужно сделать, это просто вызвать obj.refresh_from_db(). Однако это приводит к исключению DoesNotExist.

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]:

Поэтому я попробовал другие решения, например, попытался явно вызвать model.objects.get(pk=inserted_obj.id) или models.objects.filter(pk=inserted_obj.id). Это тоже не работает. Вот выданный запрос для последнего варианта.

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]:

Очевидно, что это не сработает, поскольку в этом случае генерируется новый случайный uuid.

Я не знаю, как действовать дальше, и на данный момент уперся в бетонную стену. Есть идеи? Спасибо.

Вернуться на верх