summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorFrançois Freitag <francois.freitag@polyconseil.fr>2016-01-10 17:54:57 +0100
committerTim Graham <timograham@gmail.com>2016-01-26 07:20:13 -0500
commitbdbe50a491ca41e7d4ebace47bfe8abe50a58211 (patch)
tree38f5b7953979f727267a5886488ecdfc7a5245ca /tests
parent13023ba86746980aace2341ba32a9419e7567751 (diff)
Fixed #25546 -- Prevented duplicate queries with nested prefetch_related().
Diffstat (limited to 'tests')
-rw-r--r--tests/prefetch_related/tests.py79
1 files changed, 79 insertions, 0 deletions
diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py
index 01c64b0959..5e64df2c70 100644
--- a/tests/prefetch_related/tests.py
+++ b/tests/prefetch_related/tests.py
@@ -1241,3 +1241,82 @@ class Ticket21760Tests(TestCase):
prefetcher = get_prefetcher(self.rooms[0], 'house')[0]
queryset = prefetcher.get_prefetch_queryset(list(Room.objects.all()))[0]
self.assertNotIn(' JOIN ', force_text(queryset.query))
+
+
+class Ticket25546Tests(TestCase):
+ """
+ Nested prefetch_related() shouldn't trigger duplicate queries for the same
+ lookup.
+
+ Before, prefetch queries were for 'addresses', 'first_time_authors', and
+ 'first_time_authors__addresses'. The last query is the duplicate.
+ """
+
+ @classmethod
+ def setUpTestData(cls):
+ cls.book1, cls.book2 = [
+ Book.objects.create(title='book1'),
+ Book.objects.create(title='book2'),
+ ]
+ cls.author11, cls.author12, cls.author21 = [
+ Author.objects.create(first_book=cls.book1, name='Author11'),
+ Author.objects.create(first_book=cls.book1, name='Author12'),
+ Author.objects.create(first_book=cls.book2, name='Author21'),
+ ]
+ cls.author1_address1, cls.author1_address2, cls.author2_address1 = [
+ AuthorAddress.objects.create(author=cls.author11, address='Happy place'),
+ AuthorAddress.objects.create(author=cls.author12, address='Haunted house'),
+ AuthorAddress.objects.create(author=cls.author21, address='Happy place'),
+ ]
+
+ def test_prefetch(self):
+ with self.assertNumQueries(3):
+ books = Book.objects.filter(
+ title__in=['book1', 'book2'],
+ ).prefetch_related(
+ Prefetch(
+ 'first_time_authors',
+ Author.objects.prefetch_related(
+ Prefetch(
+ 'addresses',
+ AuthorAddress.objects.filter(address='Happy place'),
+ )
+ ),
+ ),
+ )
+ book1, book2 = list(books)
+
+ with self.assertNumQueries(0):
+ self.assertListEqual(list(book1.first_time_authors.all()), [self.author11, self.author12])
+ self.assertListEqual(list(book2.first_time_authors.all()), [self.author21])
+
+ self.assertListEqual(list(book1.first_time_authors.all()[0].addresses.all()), [self.author1_address1])
+ self.assertListEqual(list(book1.first_time_authors.all()[1].addresses.all()), [])
+ self.assertListEqual(list(book2.first_time_authors.all()[0].addresses.all()), [self.author2_address1])
+
+ def test_prefetch_with_to_attr(self):
+ with self.assertNumQueries(3):
+ books = Book.objects.filter(
+ title__in=['book1', 'book2'],
+ ).prefetch_related(
+ Prefetch(
+ 'first_time_authors',
+ Author.objects.prefetch_related(
+ Prefetch(
+ 'addresses',
+ AuthorAddress.objects.filter(address='Happy place'),
+ to_attr='happy_place',
+ )
+ ),
+ to_attr='first_authors',
+ ),
+ )
+ book1, book2 = list(books)
+
+ with self.assertNumQueries(0):
+ self.assertListEqual(book1.first_authors, [self.author11, self.author12])
+ self.assertListEqual(book2.first_authors, [self.author21])
+
+ self.assertListEqual(book1.first_authors[0].happy_place, [self.author1_address1])
+ self.assertListEqual(book1.first_authors[1].happy_place, [])
+ self.assertListEqual(book2.first_authors[0].happy_place, [self.author2_address1])