Opened 7 years ago
Closed 7 years ago
#30343 closed Bug (fixed)
Prefetch related is not working when used GFK for model that uses UUID field as PK.
| Reported by: | Timur | Owned by: | Mariusz Felisiak |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | prefetch_related, UUID, generic foreign key |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
How to reproduce:
- create model with UUID as primary key
class Foo(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
...
- create another model with GFK to model Foo
class Bar(models.Model):
foo_content_type = models.ForeignKey(
ContentType, related_name='actor',
on_delete=models.CASCADE, db_index=True
)
foo_object_id = models.CharField(max_length=255, db_index=True)
foo = GenericForeignKey('foo_content_type', 'foo_object_id')
...
- and try to get queryset with prefetch related (django orm engine return None for attribute foo):
Bar.objects.all().prefetch_related('foo')
Thanks a lot for your attention! Also i wanna point out some related bug report from third party library in which previously i faced with that issue, maybe it would useful – https://github.com/justquick/django-activity-stream/issues/245
Attachments (1)
Change History (10)
comment:1 by , 7 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
| Version: | 2.2 → master |
comment:2 by , 7 years ago
| Resolution: | wontfix |
|---|---|
| Status: | closed → new |
| Triage Stage: | Unreviewed → Accepted |
Sorry for previous comment.
This should work. Currently it works when foo_object_id is an UUIDField but doesn't work when it is a CharField.
by , 7 years ago
| Attachment: | 30343-test.diff added |
|---|
comment:3 by , 7 years ago
IMO, adding get_prep_value() to the UUIDField should fix this issue 🤔:
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 2307dcae25..0a7a6b9736 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -2335,6 +2335,12 @@ class UUIDField(Field):
return value
return value.hex
+ def get_prep_value(self, value):
+ value = super().get_prep_value(value)
+ if value is None:
+ return None
+ return self.to_python(value)
+
def to_python(self, value):
if value is not None and not isinstance(value, uuid.UUID):
input_form = 'int' if isinstance(value, int) else 'hex'
comment:4 by , 7 years ago
Yeah that seems like the correct approach. I was about to suggest
-
django/contrib/contenttypes/fields.py
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py index ed98ecb48c..6098b71a39 100644
a b class GenericForeignKey(FieldCacheMixin): 202 202 else: 203 203 model = self.get_content_type(id=ct_id, 204 204 using=obj._state.db).model_class() 205 return (model._meta.pk. get_prep_value(getattr(obj, self.fk_field)),205 return (model._meta.pk.to_python(getattr(obj, self.fk_field)), 206 206 model)
But it looks like this is really just an issue with UUIDField.
comment:5 by , 7 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:8 by , 7 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Thanks for the report,
howeverGenericForeignKeydoesn't supportprefetch_related(), from the same reason it doesn't not support alsofilter(),exclude(), etc. Please see documentation.