Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #17838 - prefetch_related fails for GenericForeignKeys when rel…

…ated object id is not a CharField/TextField

Thanks to mkai for the report and debugging, and tmitchell and Przemek
Lewandowski for their work on the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17744 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b018128ea5f9ad494afb0007c597bc61630dc087 1 parent 8ef60df
@spookylukey spookylukey authored
View
10 django/contrib/contenttypes/generic.py
@@ -85,16 +85,16 @@ def get_prefetch_query_set(self, instances):
ret_val.extend(ct.get_all_objects_for_this_type(pk__in=fkeys))
# For doing the join in Python, we have to match both the FK val and the
- # content type, so the 'attr' vals we return need to be callables that
- # will return a (fk, class) pair.
+ # content type, so we use a callable that returns a (fk, class) pair.
def gfk_key(obj):
ct_id = getattr(obj, ct_attname)
if ct_id is None:
return None
else:
- return (getattr(obj, self.fk_field),
- self.get_content_type(id=ct_id,
- using=obj._state.db).model_class())
+ 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 (ret_val,
lambda obj: (obj._get_pk_val(), obj.__class__),
View
9 tests/modeltests/prefetch_related/models.py
@@ -125,6 +125,15 @@ class Bookmark(models.Model):
tags = generic.GenericRelation(TaggedItem)
+class Comment(models.Model):
+ comment = models.TextField()
+
+ # Content-object field
+ content_type = models.ForeignKey(ContentType)
+ object_pk = models.TextField()
+ content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")
+
+
## Models for lookup ordering tests
View
10 tests/modeltests/prefetch_related/tests.py
@@ -5,7 +5,7 @@
from .models import (Author, Book, Reader, Qualification, Teacher, Department,
TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge,
- BookWithYear, Person, House, Room, Employee)
+ BookWithYear, Person, House, Room, Employee, Comment)
class PrefetchRelatedTests(TestCase):
@@ -254,6 +254,14 @@ def test_prefetch_GFK(self):
qs = TaggedItem.objects.prefetch_related('content_object')
list(qs)
+ def test_prefetch_GFK_nonint_pk(self):
+ Comment.objects.create(comment="awesome", content_object=self.book1)
+
+ # 1 for Comment table, 1 for Book table
+ with self.assertNumQueries(2):
+ qs = Comment.objects.prefetch_related('content_object')
+ [c.content_object for c in qs]
+
def test_traverse_GFK(self):
"""
Test that we can traverse a 'content_object' with prefetch_related() and
View
7 tests/regressiontests/comment_tests/tests/model_tests.py
@@ -49,3 +49,10 @@ def testForModel(self):
author_comments = list(Comment.objects.for_model(Author.objects.get(pk=1)))
self.assertEqual(article_comments, [c1, c3])
self.assertEqual(author_comments, [c2])
+
+ def testPrefetchRelated(self):
+ c1, c2, c3, c4 = self.createSomeComments()
+ # one for comments, one for Articles, one for Author
+ with self.assertNumQueries(3):
+ qs = Comment.objects.prefetch_related('content_object')
+ [c.content_object for c in qs]
Please sign in to comment.
Something went wrong with that request. Please try again.