在Postgres中使用UUIField和RandomUUID时,保存后Django ORM主键不可用

2024-06-16 14:39:20 发布

您现在位置:Python中文网/ 问答频道 /正文

对于我正在处理的项目,在其中一个模型中,我使用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'

这里的问题是,我需要在将对象插入数据库后立即访问主键,但是在调用save后尝试访问pkid只会返回一个文本字符串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()的查询,然后访问返回实例的idpk,它将按预期工作

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'

这不能使用,因为不能保证firstlast返回我刚刚插入数据库的行。这让我相信,也许我所需要做的只是一个简单的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

我不清楚该如何进行,我在这一点上碰到了一堵水泥墙。有什么想法吗? 谢谢


Tags: djangonameinfromidtruedefaultdb