From 514b2c989a948e3c59bda0da0c9427acf643cf5b Mon Sep 17 00:00:00 2001 From: Mike Hansen Date: Wed, 18 Oct 2017 12:05:08 -0700 Subject: [PATCH] Fixed #28723 -- Fixed RelatedManager's prefetch_related() cache name. --- django/db/models/fields/related_descriptors.py | 4 ++-- tests/prefetch_related/tests.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index 5c6677155d..a5d4a514b7 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -581,7 +581,7 @@ def create_reverse_many_to_one_manager(superclass, rel): def get_queryset(self): try: - return self.instance._prefetched_objects_cache[self.field.related_query_name()] + return self.instance._prefetched_objects_cache[self.field.remote_field.get_cache_name()] except (AttributeError, KeyError): queryset = super().get_queryset() return self._apply_rel_filters(queryset) @@ -604,7 +604,7 @@ def create_reverse_many_to_one_manager(superclass, rel): for rel_obj in queryset: instance = instances_dict[rel_obj_attr(rel_obj)] setattr(rel_obj, self.field.name, instance) - cache_name = self.field.related_query_name() + cache_name = self.field.remote_field.get_cache_name() return queryset, rel_obj_attr, instance_attr, False, cache_name, False def add(self, *objs, bulk=True): diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py index 36d60ea1f4..adadfa33b2 100644 --- a/tests/prefetch_related/tests.py +++ b/tests/prefetch_related/tests.py @@ -2,7 +2,7 @@ from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist from django.db import connection from django.db.models import Prefetch, QuerySet -from django.db.models.query import get_prefetcher +from django.db.models.query import get_prefetcher, prefetch_related_objects from django.test import TestCase, override_settings from django.test.utils import CaptureQueriesContext @@ -1329,6 +1329,8 @@ class DirectPrefechedObjectCacheReuseTests(TestCase): AuthorAddress.objects.create(author=cls.author12, address='Haunted house'), AuthorAddress.objects.create(author=cls.author21, address='Happy place'), ] + cls.bookwithyear1 = BookWithYear.objects.create(title='Poems', published_year=2010) + cls.bookreview1 = BookReview.objects.create(book=cls.bookwithyear1) def test_detect_is_fetched(self): """ @@ -1405,6 +1407,14 @@ class DirectPrefechedObjectCacheReuseTests(TestCase): self.assertEqual(book1.first_authors[1].happy_place, []) self.assertEqual(book2.first_authors[0].happy_place, [self.author2_address1]) + def test_prefetch_reverse_foreign_key(self): + with self.assertNumQueries(2): + bookwithyear1, = BookWithYear.objects.prefetch_related('bookreview_set') + with self.assertNumQueries(0): + self.assertCountEqual(bookwithyear1.bookreview_set.all(), [self.bookreview1]) + with self.assertNumQueries(0): + prefetch_related_objects([bookwithyear1], 'bookreview_set') + class ReadPrefetchedObjectsCacheTests(TestCase): @classmethod