[英]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.