Author: lukeplant
Date: 2012-03-15 08:06:57 -0700 (Thu, 15 Mar 2012)
New Revision: 17744
Modified:
django/trunk/django/contrib/contenttypes/generic.py
django/trunk/tests/modeltests/prefetch_related/models.py
django/trunk/tests/modeltests/prefetch_related/tests.py
django/trunk/tests/regressiontests/comment_tests/tests/model_tests.py
Log:
Fixed #17838 - prefetch_related fails for GenericForeignKeys when related
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.
Modified: django/trunk/django/contrib/contenttypes/generic.py
===================================================================
--- django/trunk/django/contrib/contenttypes/generic.py 2012-03-15 13:16:27 UTC
(rev 17743)
+++ django/trunk/django/contrib/contenttypes/generic.py 2012-03-15 15:06:57 UTC
(rev 17744)
@@ -85,16 +85,16 @@
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__),
Modified: django/trunk/tests/modeltests/prefetch_related/models.py
===================================================================
--- django/trunk/tests/modeltests/prefetch_related/models.py 2012-03-15
13:16:27 UTC (rev 17743)
+++ django/trunk/tests/modeltests/prefetch_related/models.py 2012-03-15
15:06:57 UTC (rev 17744)
@@ -125,6 +125,15 @@
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
Modified: django/trunk/tests/modeltests/prefetch_related/tests.py
===================================================================
--- django/trunk/tests/modeltests/prefetch_related/tests.py 2012-03-15
13:16:27 UTC (rev 17743)
+++ django/trunk/tests/modeltests/prefetch_related/tests.py 2012-03-15
15:06:57 UTC (rev 17744)
@@ -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 @@
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
Modified: django/trunk/tests/regressiontests/comment_tests/tests/model_tests.py
===================================================================
--- django/trunk/tests/regressiontests/comment_tests/tests/model_tests.py
2012-03-15 13:16:27 UTC (rev 17743)
+++ django/trunk/tests/regressiontests/comment_tests/tests/model_tests.py
2012-03-15 15:06:57 UTC (rev 17744)
@@ -49,3 +49,10 @@
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]
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.