简体   繁体   English

与UUIDField的模型一起使用时,GenericForeignKey获取错误的id

[英]GenericForeignKey gets wrong id when used with model with UUIDField

When using GenericForeignKey together with UUIDField , what is the recommended way to get a queryset of the "real model" from a queryset of generic objects? 当使用GenericForeignKey连同UUIDField ,什么是推荐的方式来获得一个通用对象的查询集“真实模式”的查询集?

Here are the models I'm testing with: 以下是我正在测试的模型:

import uuid
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models

class Foo(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)

class Generic(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.CharField(max_length=255)
    content_object = GenericForeignKey()

and this is what I've tried so far: 这是我到目前为止所尝试的:

>>> from django.db.models import Subquery
>>> from foo.models import Foo, Generic

>>> f = Foo.objects.create()
>>> g = Generic.objects.create(content_object=f)
>>> Foo.objects.filter(id__in=Subquery(Generic.objects.all().values('object_id')))
<QuerySet []>

>>> Generic.objects.get().object_id
'997eaf64-a115-4f48-b3ac-8cbcc21274a8'
>>> Foo.objects.get().pk
UUID('997eaf64-a115-4f48-b3ac-8cbcc21274a8')

I'm guessing this has to do with the UUIDs being saved without the hyphens for the UUIDField . 我猜这与没有UUIDField连字符的UUID保存UUIDField I can't make object_id into a UUIDField either since I need other models that have integers and strings as primary keys. 我无法将object_id变成UUIDField ,因为我需要其他模型将整数和字符串作为主键。

I'm using Django 1.11 but I've also tested Django 2.0 which has the same problem. 我正在使用Django 1.11,但我也测试了Django 2.0,它有同样的问题。

the main trouble is in the explicit type casts 主要的麻烦在于explicit type casts

so, the idea of @Alasdair, you can to try: 所以,@ Alasdair的想法,你可以尝试:

foo_content_type = ContentType.objects.get_for_model(Foo)
gids = Generic.objects.filter(content_type=foo_content_type)
# create list of uuid strings
gids = list(gids.values_list('object_id', flat=True))
Foo.objects.filter(pk__in=gids)

Other solution: you can add uuid field to the Generic models. 其他解决方案:您可以将uuid字段添加到Generic模型中。 For example: 例如:

class Generic(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.CharField(max_length=255)
    content_object = GenericForeignKey()
    uuid4 = models.UUIDField(blank=True, null=True)

    def save(self, *args, **kwargs):
        try:
            self.uuid4 = uuid.UUID(self.object_id)
        except Exception as e:
            pass
        super().save(*args, **kwargs)

and queryset will look: 和queryset将看起来:

foo_content_type = ContentType.objects.get_for_model(Foo)
gids = Generic.objects.filter(content_type=foo_content_type).values('uuid4')
Foo.objects.filter(pk__in=gids)

Try removing the Subquery() . 尝试删除Subquery() You'll also want to filter by content type. 您还需要按内容类型进行过滤。

foo_content_type = ContentType.objects.get_for_model(Foo)
Foo.objects.filter(
    id__in=Generic.objects.filter(content_type=foo_content_type).values('object_id'), 
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM