mirror of
https://github.com/django/django.git
synced 2025-01-03 15:06:09 +00:00
Fixed #34889 -- Fixed get_prefetch_queryset() fallback in prefetch_one_level().
Thanks Matt Westcott for the report.
Regression in cac94dd8aa
.
This commit is contained in:
parent
90c75dc4f3
commit
296b75a3c0
@ -2550,6 +2550,9 @@ def prefetch_one_level(instances, prefetcher, lookup, level):
|
|||||||
RemovedInDjango60Warning,
|
RemovedInDjango60Warning,
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
|
queryset = None
|
||||||
|
if querysets := lookup.get_current_querysets(level):
|
||||||
|
queryset = querysets[0]
|
||||||
(
|
(
|
||||||
rel_qs,
|
rel_qs,
|
||||||
rel_obj_attr,
|
rel_obj_attr,
|
||||||
@ -2557,9 +2560,7 @@ def prefetch_one_level(instances, prefetcher, lookup, level):
|
|||||||
single,
|
single,
|
||||||
cache_name,
|
cache_name,
|
||||||
is_descriptor,
|
is_descriptor,
|
||||||
) = prefetcher.get_prefetch_queryset(
|
) = prefetcher.get_prefetch_queryset(instances, queryset)
|
||||||
instances, lookup.get_current_querysets(level)
|
|
||||||
)
|
|
||||||
# We have to handle the possibility that the QuerySet we just got back
|
# We have to handle the possibility that the QuerySet we just got back
|
||||||
# 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
|
||||||
|
@ -4,10 +4,12 @@ from django.contrib.contenttypes.models import ContentType
|
|||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import NotSupportedError, connection
|
from django.db import NotSupportedError, connection
|
||||||
from django.db.models import Prefetch, QuerySet, prefetch_related_objects
|
from django.db.models import Prefetch, QuerySet, prefetch_related_objects
|
||||||
from django.db.models.query import get_prefetcher
|
from django.db.models.fields.related import ForwardManyToOneDescriptor
|
||||||
|
from django.db.models.query import get_prefetcher, prefetch_one_level
|
||||||
from django.db.models.sql import Query
|
from django.db.models.sql import Query
|
||||||
from django.test import (
|
from django.test import (
|
||||||
TestCase,
|
TestCase,
|
||||||
|
ignore_warnings,
|
||||||
override_settings,
|
override_settings,
|
||||||
skipIfDBFeature,
|
skipIfDBFeature,
|
||||||
skipUnlessDBFeature,
|
skipUnlessDBFeature,
|
||||||
@ -1997,7 +1999,7 @@ class PrefetchLimitTests(TestDataMixin, TestCase):
|
|||||||
list(Book.objects.prefetch_related(Prefetch("authors", authors[1:])))
|
list(Book.objects.prefetch_related(Prefetch("authors", authors[1:])))
|
||||||
|
|
||||||
|
|
||||||
class GetCurrentQuerySetDeprecation(TestCase):
|
class DeprecationTests(TestCase):
|
||||||
def test_get_current_queryset_warning(self):
|
def test_get_current_queryset_warning(self):
|
||||||
msg = (
|
msg = (
|
||||||
"Prefetch.get_current_queryset() is deprecated. Use "
|
"Prefetch.get_current_queryset() is deprecated. Use "
|
||||||
@ -2011,3 +2013,41 @@ class GetCurrentQuerySetDeprecation(TestCase):
|
|||||||
)
|
)
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
|
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
|
||||||
self.assertIsNone(Prefetch("authors").get_current_queryset(1))
|
self.assertIsNone(Prefetch("authors").get_current_queryset(1))
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
|
def test_prefetch_one_level_fallback(self):
|
||||||
|
class NoGetPrefetchQuerySetsDescriptor(ForwardManyToOneDescriptor):
|
||||||
|
def get_prefetch_queryset(self, instances, queryset=None):
|
||||||
|
if queryset is None:
|
||||||
|
return super().get_prefetch_querysets(instances)
|
||||||
|
return super().get_prefetch_querysets(instances, [queryset])
|
||||||
|
|
||||||
|
def __getattribute__(self, name):
|
||||||
|
if name == "get_prefetch_querysets":
|
||||||
|
raise AttributeError
|
||||||
|
return super().__getattribute__(name)
|
||||||
|
|
||||||
|
house = House.objects.create()
|
||||||
|
room = Room.objects.create(house=house)
|
||||||
|
house.main_room = room
|
||||||
|
house.save()
|
||||||
|
|
||||||
|
# prefetch_one_level() fallbacks to get_prefetch_queryset().
|
||||||
|
prefetcher = NoGetPrefetchQuerySetsDescriptor(Room._meta.get_field("house"))
|
||||||
|
obj_list, additional_lookups = prefetch_one_level(
|
||||||
|
[room],
|
||||||
|
prefetcher,
|
||||||
|
Prefetch("house", House.objects.all()),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
self.assertEqual(obj_list, [house])
|
||||||
|
self.assertEqual(additional_lookups, [])
|
||||||
|
|
||||||
|
obj_list, additional_lookups = prefetch_one_level(
|
||||||
|
[room],
|
||||||
|
prefetcher,
|
||||||
|
Prefetch("house"),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
self.assertEqual(obj_list, [house])
|
||||||
|
self.assertEqual(additional_lookups, [])
|
||||||
|
Loading…
Reference in New Issue
Block a user