summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Gama <cliffygamy@gmail.com>2025-03-15 11:13:46 +0200
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-03-26 09:55:38 +0100
commitd5c19f9b327fccc1f707e10de648fe9d4cdacb9b (patch)
tree5d9d0aa6b358b1b0204c2917192c1039081b56ac
parent7d9aab8da0a06787d649762a702e1a518d843a63 (diff)
Fixed #34819 -- Made GenericForeignKey prefetching use matching pk representations.
Ensured that rel_obj_attr and instance_attr return matching (pk, cls) tuples in GenericForeignKey.get_prefetch_queryset(), preventing mismatches when prefetching related objects where pk and get_prep_value() differ. Using value_to_string() also makes this code compatible with composite primary keys.
-rw-r--r--django/contrib/contenttypes/fields.py7
-rw-r--r--tests/prefetch_related/models.py9
-rw-r--r--tests/prefetch_related/tests.py9
3 files changed, 20 insertions, 5 deletions
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py
index 272cb2b02c..f9d896bc13 100644
--- a/django/contrib/contenttypes/fields.py
+++ b/django/contrib/contenttypes/fields.py
@@ -205,14 +205,11 @@ class GenericForeignKey(FieldCacheMixin, Field):
model = self.get_content_type(
id=ct_id, using=obj._state.db
).model_class()
- return (
- model._meta.pk.get_prep_value(getattr(obj, self.fk_field)),
- model,
- )
+ return str(getattr(obj, self.fk_field)), model
return (
ret_val,
- lambda obj: (obj.pk, obj.__class__),
+ lambda obj: (obj._meta.pk.value_to_string(obj), obj.__class__),
gfk_key,
True,
self.name,
diff --git a/tests/prefetch_related/models.py b/tests/prefetch_related/models.py
index 2f37cde1c8..e12eabdfb2 100644
--- a/tests/prefetch_related/models.py
+++ b/tests/prefetch_related/models.py
@@ -216,6 +216,15 @@ class Comment(models.Model):
ordering = ["id"]
+class ArticleCustomUUID(models.Model):
+ class CustomUUIDField(models.UUIDField):
+ def get_prep_value(self, value):
+ return str(value)
+
+ id = CustomUUIDField(primary_key=True, default=uuid.uuid4)
+ name = models.CharField(max_length=30)
+
+
# Models for lookup ordering tests
diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py
index 72c499df7f..49acfdd7c8 100644
--- a/tests/prefetch_related/tests.py
+++ b/tests/prefetch_related/tests.py
@@ -16,6 +16,7 @@ from django.test.utils import CaptureQueriesContext
from .models import (
Article,
+ ArticleCustomUUID,
Author,
Author2,
AuthorAddress,
@@ -1179,6 +1180,14 @@ class GenericRelationTests(TestCase):
qs = Comment.objects.prefetch_related("content_object_uuid")
self.assertEqual([c.content_object_uuid for c in qs], [article])
+ def test_prefetch_GFK_uses_prepped_primary_key(self):
+ article = ArticleCustomUUID.objects.create(name="Blanche")
+ Comment.objects.create(comment="Enchantment", content_object_uuid=article)
+ obj = Comment.objects.prefetch_related("content_object_uuid").get(
+ comment="Enchantment"
+ )
+ self.assertEqual(obj.content_object_uuid, article)
+
def test_prefetch_GFK_fk_pk(self):
book = Book.objects.create(title="Poems")
book_with_year = BookWithYear.objects.create(book=book, published_year=2019)