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.

Reply via email to