From 6104875a2cc797bbd1254aa61f22a9b03d652128 Mon Sep 17 00:00:00 2001
From: Paulo <commonzenpython@gmail.com>
Date: Sun, 27 May 2018 13:48:24 +0200
Subject: [PATCH] Fixed #29230 -- Fixed nested prefetches that clash with
 descriptors.

---
 django/db/models/query.py       |  2 +-
 tests/prefetch_related/tests.py | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/django/db/models/query.py b/django/db/models/query.py
index 1ef20d01d9..5ae451879c 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1568,7 +1568,7 @@ def prefetch_related_objects(model_instances, *related_lookups):
                 # same relationships to stop infinite recursion. So, if we
                 # are already on an automatically added lookup, don't add
                 # the new lookups from relationships we've seen already.
-                if not (lookup in auto_lookups and descriptor in followed_descriptors):
+                if not (prefetch_to in done_queries and lookup in auto_lookups and descriptor in followed_descriptors):
                     done_queries[prefetch_to] = obj_list
                     new_lookups = normalize_prefetch_lookups(reversed(additional_lookups), prefetch_to)
                     auto_lookups.update(new_lookups)
diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py
index 5a701bffec..9201ff3853 100644
--- a/tests/prefetch_related/tests.py
+++ b/tests/prefetch_related/tests.py
@@ -772,6 +772,19 @@ class CustomPrefetchTests(TestCase):
             self.room2_1
         )
 
+    def test_nested_prefetch_related_with_duplicate_prefetcher(self):
+        """
+        Nested prefetches whose name clashes with descriptor names
+        (Person.houses here) are allowed.
+        """
+        occupants = Person.objects.prefetch_related(
+            Prefetch('houses', to_attr='some_attr_name'),
+            Prefetch('houses', queryset=House.objects.prefetch_related('main_room')),
+        )
+        houses = House.objects.prefetch_related(Prefetch('occupants', queryset=occupants))
+        with self.assertNumQueries(5):
+            self.traverse_qs(list(houses), [['occupants', 'houses', 'main_room']])
+
     def test_values_queryset(self):
         with self.assertRaisesMessage(ValueError, 'Prefetch querysets cannot use values().'):
             Prefetch('houses', House.objects.values('pk'))