diff options
| author | Gagaro <gagaro42@gmail.com> | 2015-05-29 18:10:52 +0200 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2015-06-18 15:42:47 -0400 |
| commit | 74261bc593bcf9411e7e25a4731dd9471499819e (patch) | |
| tree | a7afbc456fb01a80df7bdb515ccc03e7c724b527 | |
| parent | 06747ee790177c549ed269e69ceac74011158f79 (diff) | |
Fixed #24873 -- Prevented nested Prefetch objects from being overwritten.
| -rw-r--r-- | django/db/models/query.py | 7 | ||||
| -rw-r--r-- | tests/prefetch_related/tests.py | 11 |
2 files changed, 17 insertions, 1 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py index 343f4dc718..55a94cebe5 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -1538,7 +1538,12 @@ def prefetch_one_level(instances, prefetcher, lookup, level): # contains some prefetch_related lookups. We don't want to trigger the # prefetch_related functionality by evaluating the query. Rather, we need # to merge in the prefetch_related lookups. - additional_lookups = getattr(rel_qs, '_prefetch_related_lookups', []) + # Copy the lookups in case it is a Prefetch object which could be reused + # later (happens in nested prefetch_related). + additional_lookups = [ + copy.copy(additional_lookup) for additional_lookup + in getattr(rel_qs, '_prefetch_related_lookups', []) + ] if additional_lookups: # Don't need to clone because the manager should have given us a fresh # instance, so we access an internal instead of using public interface diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py index f059a6f7ca..d9e7488d42 100644 --- a/tests/prefetch_related/tests.py +++ b/tests/prefetch_related/tests.py @@ -626,6 +626,17 @@ class CustomPrefetchTests(TestCase): room = Room.objects.filter(main_room_of__isnull=False).prefetch_related(Prefetch('main_room_of', queryset=houses.filter(address='DoesNotExist'), to_attr='main_room_of_attr')).first() self.assertIsNone(room.main_room_of_attr) + def test_nested_prefetch_related_are_not_overwritten(self): + # Regression test for #24873 + houses_2 = House.objects.prefetch_related(Prefetch('rooms')) + persons = Person.objects.prefetch_related(Prefetch('houses', queryset=houses_2)) + houses = House.objects.prefetch_related(Prefetch('occupants', queryset=persons)) + list(houses) # queryset must be evaluated once to reproduce the bug. + self.assertEqual( + houses.all()[0].occupants.all()[0].houses.all()[1].rooms.all()[0], + self.room2_1 + ) + class DefaultManagerTests(TestCase): |
