From 8b21878357364a461bae711c4d0011a8f338b160 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 5 Feb 2018 08:02:57 -0800 Subject: [PATCH] Refs #28723 -- Fixed stale prefetch_related cache after add/remove. Regression in 514b2c989a948e3c59bda0da0c9427acf643cf5b. --- django/db/models/fields/related_descriptors.py | 2 +- tests/prefetch_related/models.py | 3 ++- tests/prefetch_related/tests.py | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index a5d4a514b7..f9b770fade 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -575,7 +575,7 @@ def create_reverse_many_to_one_manager(superclass, rel): def _remove_prefetched_objects(self): try: - self.instance._prefetched_objects_cache.pop(self.field.related_query_name()) + self.instance._prefetched_objects_cache.pop(self.field.remote_field.get_cache_name()) except (AttributeError, KeyError): pass # nothing to clear from cache diff --git a/tests/prefetch_related/models.py b/tests/prefetch_related/models.py index 68fdc2686d..cb64b52a15 100644 --- a/tests/prefetch_related/models.py +++ b/tests/prefetch_related/models.py @@ -86,7 +86,8 @@ class Reader(models.Model): class BookReview(models.Model): - book = models.ForeignKey(BookWithYear, models.CASCADE) + # Intentionally does not have a related name. + book = models.ForeignKey(BookWithYear, models.CASCADE, null=True) notes = models.TextField(null=True, blank=True) diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py index adadfa33b2..e92d7f349f 100644 --- a/tests/prefetch_related/tests.py +++ b/tests/prefetch_related/tests.py @@ -1415,6 +1415,21 @@ class DirectPrefechedObjectCacheReuseTests(TestCase): with self.assertNumQueries(0): prefetch_related_objects([bookwithyear1], 'bookreview_set') + def test_add_clears_prefetched_objects(self): + bookwithyear = BookWithYear.objects.get(pk=self.bookwithyear1.pk) + prefetch_related_objects([bookwithyear], 'bookreview_set') + self.assertCountEqual(bookwithyear.bookreview_set.all(), [self.bookreview1]) + new_review = BookReview.objects.create() + bookwithyear.bookreview_set.add(new_review) + self.assertCountEqual(bookwithyear.bookreview_set.all(), [self.bookreview1, new_review]) + + def test_remove_clears_prefetched_objects(self): + bookwithyear = BookWithYear.objects.get(pk=self.bookwithyear1.pk) + prefetch_related_objects([bookwithyear], 'bookreview_set') + self.assertCountEqual(bookwithyear.bookreview_set.all(), [self.bookreview1]) + bookwithyear.bookreview_set.remove(self.bookreview1) + self.assertCountEqual(bookwithyear.bookreview_set.all(), []) + class ReadPrefetchedObjectsCacheTests(TestCase): @classmethod