Author: lukeplant
Date: 2012-02-29 16:57:01 -0800 (Wed, 29 Feb 2012)
New Revision: 17605

Modified:
   django/trunk/django/contrib/contenttypes/generic.py
   django/trunk/django/db/models/fields/related.py
   django/trunk/tests/modeltests/prefetch_related/tests.py
Log:
Fixed #17696 - Queryset prefetch_related() ignores using()

Thanks to simon29 for the report.

Modified: django/trunk/django/contrib/contenttypes/generic.py
===================================================================
--- django/trunk/django/contrib/contenttypes/generic.py 2012-02-29 20:12:16 UTC 
(rev 17604)
+++ django/trunk/django/contrib/contenttypes/generic.py 2012-03-01 00:57:01 UTC 
(rev 17605)
@@ -321,7 +321,7 @@
                 return super(GenericRelatedObjectManager, 
self).get_query_set().using(db).filter(**self.core_filters)
 
         def get_prefetch_query_set(self, instances):
-            db = self._db or router.db_for_read(self.model)
+            db = self._db or router.db_for_read(self.model, 
instance=instances[0])
             query = {
                 '%s__pk' % self.content_type_field_name: self.content_type.id,
                 '%s__in' % self.object_id_field_name:

Modified: django/trunk/django/db/models/fields/related.py
===================================================================
--- django/trunk/django/db/models/fields/related.py     2012-02-29 20:12:16 UTC 
(rev 17604)
+++ django/trunk/django/db/models/fields/related.py     2012-03-01 00:57:01 UTC 
(rev 17605)
@@ -239,7 +239,7 @@
     def get_prefetch_query_set(self, instances):
         vals = set(instance._get_pk_val() for instance in instances)
         params = {'%s__pk__in' % self.related.field.name: vals}
-        return (self.get_query_set(),
+        return (self.get_query_set(instance=instances[0]),
                 attrgetter(self.related.field.attname),
                 lambda obj: obj._get_pk_val(),
                 True,
@@ -322,7 +322,7 @@
             params = {'%s__pk__in' % self.field.rel.field_name: vals}
         else:
             params = {'%s__in' % self.field.rel.field_name: vals}
-        return (self.get_query_set().filter(**params),
+        return (self.get_query_set(instance=instances[0]).filter(**params),
                 attrgetter(self.field.rel.field_name),
                 attrgetter(self.field.attname),
                 True,
@@ -461,7 +461,7 @@
                     return super(RelatedManager, 
self).get_query_set().using(db).filter(**self.core_filters)
 
             def get_prefetch_query_set(self, instances):
-                db = self._db or router.db_for_read(self.model)
+                db = self._db or router.db_for_read(self.model, 
instance=instances[0])
                 query = {'%s__%s__in' % (rel_field.name, attname):
                              set(getattr(obj, attname) for obj in instances)}
                 qs = super(RelatedManager, 
self).get_query_set().using(db).filter(**query)
@@ -543,8 +543,9 @@
                 return super(ManyRelatedManager, 
self).get_query_set().using(db)._next_is_sticky().filter(**self.core_filters)
 
         def get_prefetch_query_set(self, instances):
+            instance = instances[0]
             from django.db import connections
-            db = self._db or router.db_for_read(self.model)
+            db = self._db or router.db_for_read(instance.__class__, 
instance=instance)
             query = {'%s__pk__in' % self.query_field_name:
                          set(obj._get_pk_val() for obj in instances)}
             qs = super(ManyRelatedManager, 
self).get_query_set().using(db)._next_is_sticky().filter(**query)

Modified: django/trunk/tests/modeltests/prefetch_related/tests.py
===================================================================
--- django/trunk/tests/modeltests/prefetch_related/tests.py     2012-02-29 
20:12:16 UTC (rev 17604)
+++ django/trunk/tests/modeltests/prefetch_related/tests.py     2012-03-01 
00:57:01 UTC (rev 17605)
@@ -483,3 +483,92 @@
             bulk = 
Employee.objects.prefetch_related('serfs').in_bulk([boss1.pk, boss2.pk])
             for b in bulk.values():
                 list(b.serfs.all())
+
+
+class MultiDbTests(TestCase):
+    multi_db = True
+
+    def test_using_is_honored_m2m(self):
+        B = Book.objects.using('other')
+        A = Author.objects.using('other')
+        book1 = B.create(title="Poems")
+        book2 = B.create(title="Jane Eyre")
+        book3 = B.create(title="Wuthering Heights")
+        book4 = B.create(title="Sense and Sensibility")
+
+        author1 = A.create(name="Charlotte", first_book=book1)
+        author2 = A.create(name="Anne", first_book=book1)
+        author3 = A.create(name="Emily", first_book=book1)
+        author4 = A.create(name="Jane", first_book=book4)
+
+        book1.authors.add(author1, author2, author3)
+        book2.authors.add(author1)
+        book3.authors.add(author3)
+        book4.authors.add(author4)
+
+        # Forward
+        qs1 = B.prefetch_related('authors')
+        with self.assertNumQueries(2, using='other'):
+            books = "".join(["%s (%s)\n" %
+                             (book.title, ", ".join(a.name for a in 
book.authors.all()))
+                             for book in qs1])
+        self.assertEqual(books,
+                         "Poems (Charlotte, Anne, Emily)\n"
+                         "Jane Eyre (Charlotte)\n"
+                         "Wuthering Heights (Emily)\n"
+                         "Sense and Sensibility (Jane)\n")
+
+        # Reverse
+        qs2 = A.prefetch_related('books')
+        with self.assertNumQueries(2, using='other'):
+            authors = "".join(["%s: %s\n" %
+                               (author.name, ", ".join(b.title for b in 
author.books.all()))
+                               for author in qs2])
+        self.assertEquals(authors,
+                          "Charlotte: Poems, Jane Eyre\n"
+                          "Anne: Poems\n"
+                          "Emily: Poems, Wuthering Heights\n"
+                          "Jane: Sense and Sensibility\n")
+
+    def test_using_is_honored_fkey(self):
+        B = Book.objects.using('other')
+        A = Author.objects.using('other')
+        book1 = B.create(title="Poems")
+        book2 = B.create(title="Sense and Sensibility")
+
+        author1 = A.create(name="Charlotte Bronte", first_book=book1)
+        author2 = A.create(name="Jane Austen", first_book=book2)
+
+        # Forward
+        with self.assertNumQueries(2, using='other'):
+            books = ", ".join(a.first_book.title for a in 
A.prefetch_related('first_book'))
+        self.assertEqual("Poems, Sense and Sensibility", books)
+
+        # Reverse
+        with self.assertNumQueries(2, using='other'):
+            books = "".join("%s (%s)\n" %
+                            (b.title, ", ".join(a.name for a in 
b.first_time_authors.all()))
+                            for b in B.prefetch_related('first_time_authors'))
+        self.assertEqual(books,
+                         "Poems (Charlotte Bronte)\n"
+                         "Sense and Sensibility (Jane Austen)\n")
+
+    def test_using_is_honored_inheritance(self):
+        B = BookWithYear.objects.using('other')
+        A = AuthorWithAge.objects.using('other')
+        book1 = B.create(title="Poems", published_year=2010)
+        book2 = B.create(title="More poems", published_year=2011)
+        author1 = A.create(name='Jane', first_book=book1, age=50)
+        author2 = A.create(name='Tom', first_book=book1, age=49)
+
+        # parent link
+        with self.assertNumQueries(2, using='other'):
+            authors = ", ".join(a.author.name for a in 
A.prefetch_related('author'))
+
+        self.assertEqual(authors, "Jane, Tom")
+
+        # child link
+        with self.assertNumQueries(2, using='other'):
+            ages = ", ".join(str(a.authorwithage.age) for a in 
A.prefetch_related('authorwithage'))
+
+        self.assertEqual(ages, "50, 49")

-- 
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