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?
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
. I can't make object_id
into a UUIDField
either since I need other models that have integers and strings as primary keys.
I'm using Django 1.11 but I've also tested Django 2.0 which has the same problem.
the main trouble is in the explicit type casts
so, the idea of @Alasdair, you can to try:
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. 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:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With