diff options
| author | François Freitag <francois.freitag@polyconseil.fr> | 2016-01-10 17:54:57 +0100 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2016-01-26 07:20:13 -0500 |
| commit | bdbe50a491ca41e7d4ebace47bfe8abe50a58211 (patch) | |
| tree | 38f5b7953979f727267a5886488ecdfc7a5245ca /tests | |
| parent | 13023ba86746980aace2341ba32a9419e7567751 (diff) | |
Fixed #25546 -- Prevented duplicate queries with nested prefetch_related().
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/prefetch_related/tests.py | 79 |
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]) |
