diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/prefetch_related/models.py | 4 | ||||
| -rw-r--r-- | tests/prefetch_related/tests.py | 182 |
2 files changed, 186 insertions, 0 deletions
diff --git a/tests/prefetch_related/models.py b/tests/prefetch_related/models.py index 405e9bba00..de2d88395d 100644 --- a/tests/prefetch_related/models.py +++ b/tests/prefetch_related/models.py @@ -28,6 +28,10 @@ class AuthorWithAge(Author): age = models.IntegerField() +class AuthorWithAgeChild(AuthorWithAge): + pass + + class FavoriteAuthors(models.Model): author = models.ForeignKey( Author, models.CASCADE, to_field="name", related_name="i_like" diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py index bd37ca0ec3..1955809aec 100644 --- a/tests/prefetch_related/tests.py +++ b/tests/prefetch_related/tests.py @@ -21,6 +21,7 @@ from .models import ( Author2, AuthorAddress, AuthorWithAge, + AuthorWithAgeChild, Bio, Book, Bookmark, @@ -2086,3 +2087,184 @@ class PrefetchLimitTests(TestDataMixin, TestCase): with self.subTest(book=book): self.assertEqual(len(book.authors_sliced), 1) self.assertIn(book.authors_sliced[0], list(book.authors.all())) + + +class PrefetchRelatedMTICacheTests(TestCase): + @classmethod + def setUpTestData(cls): + cls.book = Book.objects.create(title="Book1") + cls.related1 = Author.objects.create(name="related1", first_book=cls.book) + cls.related2 = Author.objects.create(name="related2", first_book=cls.book) + cls.related3 = Author.objects.create(name="related3", first_book=cls.book) + cls.related4 = Author.objects.create(name="related4", first_book=cls.book) + + cls.child = AuthorWithAgeChild.objects.create( + name="child", + age=31, + first_book=cls.book, + ) + cls.m2m_child = AuthorWithAgeChild.objects.create( + name="m2m_child", + age=31, + first_book=cls.book, + ) + cls.m2m_child.favorite_authors.set([cls.related1, cls.related2, cls.related3]) + + def test_parent_fk_available_in_child(self): + qs = ( + Author.objects.select_related("authorwithage") + .prefetch_related("first_book") + .filter(pk=self.child.pk) + ) + with self.assertNumQueries(2): + results = list(qs) + self.assertEqual(len(results), 1) + self.assertEqual(results[0].authorwithage.first_book, self.book) + + def test_grandparent_fk_available_in_child(self): + qs = ( + Author.objects.select_related( + "authorwithage", "authorwithage__authorwithagechild" + ) + .prefetch_related("first_book") + .filter(pk=self.child.pk) + ) + with self.assertNumQueries(2): + results = list(qs) + self.assertEqual(len(results), 1) + self.assertEqual( + results[0].authorwithage.authorwithagechild.first_book, self.book + ) + + def test_parent_m2m_available_in_child(self): + qs = ( + Author.objects.select_related("authorwithage") + .prefetch_related("favorite_authors") + .filter(pk=self.m2m_child.pk) + ) + with self.assertNumQueries(2): + results = list(qs) + self.assertEqual(len(results), 1) + self.assertQuerySetEqual( + results[0].authorwithage.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + + def test_grandparent_m2m_available_in_child(self): + qs = ( + Author.objects.select_related( + "authorwithage", "authorwithage__authorwithagechild" + ) + .prefetch_related("favorite_authors") + .filter(pk=self.m2m_child.pk) + ) + with self.assertNumQueries(2): + results = list(qs) + self.assertEqual(len(results), 1) + self.assertQuerySetEqual( + set(results[0].authorwithage.authorwithagechild.favorite_authors.all()), + {self.related1, self.related2, self.related3}, + ) + + def test_add_clears_prefetched_objects_in_parent(self): + gp = ( + Author.objects.select_related("authorwithage") + .prefetch_related("favorite_authors") + .get(pk=self.m2m_child.pk) + ) + self.assertQuerySetEqual( + gp.favorite_authors.all(), + {self.related1, self.related2, self.related3}, + ) + self.assertQuerySetEqual( + gp.authorwithage.favorite_authors.all(), + {self.related1, self.related2, self.related3}, + ) + gp.authorwithage.favorite_authors.add(self.related4) + self.assertQuerySetEqual( + gp.favorite_authors.all(), + {self.related1, self.related2, self.related3, self.related4}, + ) + self.assertQuerySetEqual( + gp.authorwithage.favorite_authors.all(), + {self.related1, self.related2, self.related3, self.related4}, + ) + + def test_add_clears_prefetched_objects_in_grandparent(self): + gp = ( + Author.objects.select_related( + "authorwithage", "authorwithage__authorwithagechild" + ) + .prefetch_related("favorite_authors") + .get(pk=self.m2m_child.pk) + ) + self.assertQuerySetEqual( + gp.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + self.assertQuerySetEqual( + gp.authorwithage.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + self.assertQuerySetEqual( + gp.authorwithage.authorwithagechild.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + gp.authorwithage.authorwithagechild.favorite_authors.add(self.related4) + self.assertQuerySetEqual( + gp.favorite_authors.all(), + [self.related1, self.related2, self.related3, self.related4], + ) + self.assertQuerySetEqual( + gp.authorwithage.favorite_authors.all(), + [self.related1, self.related2, self.related3, self.related4], + ) + self.assertQuerySetEqual( + gp.authorwithage.authorwithagechild.favorite_authors.all(), + [self.related1, self.related2, self.related3, self.related4], + ) + + def test_remove_clears_prefetched_objects_in_parent(self): + gp = ( + Author.objects.select_related("authorwithage") + .prefetch_related("favorite_authors") + .get(pk=self.m2m_child.pk) + ) + self.assertQuerySetEqual( + gp.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + self.assertQuerySetEqual( + gp.authorwithage.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + gp.authorwithage.favorite_authors.clear() + self.assertQuerySetEqual(gp.favorite_authors.all(), []) + self.assertQuerySetEqual(gp.authorwithage.favorite_authors.all(), []) + + def test_remove_clears_prefetched_objects_in_grandparent(self): + gp = ( + Author.objects.select_related( + "authorwithage", "authorwithage__authorwithagechild" + ) + .prefetch_related("favorite_authors") + .get(pk=self.m2m_child.pk) + ) + self.assertQuerySetEqual( + gp.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + self.assertQuerySetEqual( + gp.authorwithage.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + self.assertQuerySetEqual( + gp.authorwithage.authorwithagechild.favorite_authors.all(), + [self.related1, self.related2, self.related3], + ) + gp.authorwithage.favorite_authors.clear() + self.assertQuerySetEqual(gp.favorite_authors.all(), []) + self.assertQuerySetEqual(gp.authorwithage.favorite_authors.all(), []) + self.assertQuerySetEqual( + gp.authorwithage.authorwithagechild.favorite_authors.all(), [] + ) |
