Kaydet (Commit) 74261bc5 authored tarafından Gagaro's avatar Gagaro Kaydeden (comit) Tim Graham

Fixed #24873 -- Prevented nested Prefetch objects from being overwritten.

üst 06747ee7
...@@ -1538,7 +1538,12 @@ def prefetch_one_level(instances, prefetcher, lookup, level): ...@@ -1538,7 +1538,12 @@ def prefetch_one_level(instances, prefetcher, lookup, level):
# contains some prefetch_related lookups. We don't want to trigger the # contains some prefetch_related lookups. We don't want to trigger the
# prefetch_related functionality by evaluating the query. Rather, we need # prefetch_related functionality by evaluating the query. Rather, we need
# to merge in the prefetch_related lookups. # 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: if additional_lookups:
# Don't need to clone because the manager should have given us a fresh # 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 # instance, so we access an internal instead of using public interface
......
...@@ -626,6 +626,17 @@ class CustomPrefetchTests(TestCase): ...@@ -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() 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) 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): class DefaultManagerTests(TestCase):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment