44from django .core .exceptions import ObjectDoesNotExist
55from django .db import NotSupportedError , connection
66from django .db .models import Prefetch , QuerySet , prefetch_related_objects
7- from django .db .models .query import get_prefetcher
7+ from django .db .models .fields .related import ForwardManyToOneDescriptor
8+ from django .db .models .query import get_prefetcher , prefetch_one_level
89from django .db .models .sql import Query
910from django .test import (
1011 TestCase ,
12+ ignore_warnings ,
1113 override_settings ,
1214 skipIfDBFeature ,
1315 skipUnlessDBFeature ,
@@ -1997,7 +1999,7 @@ def test_window_not_supported(self):
19971999 list (Book .objects .prefetch_related (Prefetch ("authors" , authors [1 :])))
19982000
19992001
2000- class GetCurrentQuerySetDeprecation (TestCase ):
2002+ class DeprecationTests (TestCase ):
20012003 def test_get_current_queryset_warning (self ):
20022004 msg = (
20032005 "Prefetch.get_current_queryset() is deprecated. Use "
@@ -2011,3 +2013,41 @@ def test_get_current_queryset_warning(self):
20112013 )
20122014 with self .assertWarnsMessage (RemovedInDjango60Warning , msg ):
20132015 self .assertIsNone (Prefetch ("authors" ).get_current_queryset (1 ))
2016+
2017+ @ignore_warnings (category = RemovedInDjango60Warning )
2018+ def test_prefetch_one_level_fallback (self ):
2019+ class NoGetPrefetchQuerySetsDescriptor (ForwardManyToOneDescriptor ):
2020+ def get_prefetch_queryset (self , instances , queryset = None ):
2021+ if queryset is None :
2022+ return super ().get_prefetch_querysets (instances )
2023+ return super ().get_prefetch_querysets (instances , [queryset ])
2024+
2025+ def __getattribute__ (self , name ):
2026+ if name == "get_prefetch_querysets" :
2027+ raise AttributeError
2028+ return super ().__getattribute__ (name )
2029+
2030+ house = House .objects .create ()
2031+ room = Room .objects .create (house = house )
2032+ house .main_room = room
2033+ house .save ()
2034+
2035+ # prefetch_one_level() fallbacks to get_prefetch_queryset().
2036+ prefetcher = NoGetPrefetchQuerySetsDescriptor (Room ._meta .get_field ("house" ))
2037+ obj_list , additional_lookups = prefetch_one_level (
2038+ [room ],
2039+ prefetcher ,
2040+ Prefetch ("house" , House .objects .all ()),
2041+ 0 ,
2042+ )
2043+ self .assertEqual (obj_list , [house ])
2044+ self .assertEqual (additional_lookups , [])
2045+
2046+ obj_list , additional_lookups = prefetch_one_level (
2047+ [room ],
2048+ prefetcher ,
2049+ Prefetch ("house" ),
2050+ 0 ,
2051+ )
2052+ self .assertEqual (obj_list , [house ])
2053+ self .assertEqual (additional_lookups , [])
0 commit comments