mirror of
https://github.com/django/django.git
synced 2025-06-05 03:29:12 +00:00
Refs #33651 -- Removed Prefetch.get_current_queryset() and get_prefetch_queryset() per deprecation timeline.
This commit is contained in:
parent
55f71b195b
commit
817bc5800b
@ -1,6 +1,5 @@
|
|||||||
import functools
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
import warnings
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from asgiref.sync import sync_to_async
|
from asgiref.sync import sync_to_async
|
||||||
@ -21,7 +20,6 @@ from django.db.models.query_utils import PathInfo
|
|||||||
from django.db.models.sql import AND
|
from django.db.models.sql import AND
|
||||||
from django.db.models.sql.where import WhereNode
|
from django.db.models.sql.where import WhereNode
|
||||||
from django.db.models.utils import AltersData
|
from django.db.models.utils import AltersData
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
@ -159,17 +157,6 @@ class GenericForeignKey(FieldCacheMixin, Field):
|
|||||||
# This should never happen. I love comments like this, don't you?
|
# This should never happen. I love comments like this, don't you?
|
||||||
raise Exception("Impossible arguments to GFK.get_content_type!")
|
raise Exception("Impossible arguments to GFK.get_content_type!")
|
||||||
|
|
||||||
def get_prefetch_queryset(self, instances, queryset=None):
|
|
||||||
warnings.warn(
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
if queryset is None:
|
|
||||||
return self.get_prefetch_querysets(instances)
|
|
||||||
return self.get_prefetch_querysets(instances, [queryset])
|
|
||||||
|
|
||||||
def get_prefetch_querysets(self, instances, querysets=None):
|
def get_prefetch_querysets(self, instances, querysets=None):
|
||||||
custom_queryset_dict = {}
|
custom_queryset_dict = {}
|
||||||
if querysets is not None:
|
if querysets is not None:
|
||||||
@ -626,17 +613,6 @@ def create_generic_related_manager(superclass, rel):
|
|||||||
queryset = super().get_queryset()
|
queryset = super().get_queryset()
|
||||||
return self._apply_rel_filters(queryset)
|
return self._apply_rel_filters(queryset)
|
||||||
|
|
||||||
def get_prefetch_queryset(self, instances, queryset=None):
|
|
||||||
warnings.warn(
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
if queryset is None:
|
|
||||||
return self.get_prefetch_querysets(instances)
|
|
||||||
return self.get_prefetch_querysets(instances, [queryset])
|
|
||||||
|
|
||||||
def get_prefetch_querysets(self, instances, querysets=None):
|
def get_prefetch_querysets(self, instances, querysets=None):
|
||||||
if querysets and len(querysets) != 1:
|
if querysets and len(querysets) != 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -63,8 +63,6 @@ and two directions (forward and reverse) for a total of six combinations.
|
|||||||
``ReverseManyToManyDescriptor``, use ``ManyToManyDescriptor`` instead.
|
``ReverseManyToManyDescriptor``, use ``ManyToManyDescriptor`` instead.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from asgiref.sync import sync_to_async
|
from asgiref.sync import sync_to_async
|
||||||
|
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
@ -81,7 +79,6 @@ from django.db.models.lookups import GreaterThan, LessThanOrEqual
|
|||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.db.models.query_utils import DeferredAttribute
|
from django.db.models.query_utils import DeferredAttribute
|
||||||
from django.db.models.utils import AltersData, resolve_callables
|
from django.db.models.utils import AltersData, resolve_callables
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
@ -155,17 +152,6 @@ class ForwardManyToOneDescriptor:
|
|||||||
def get_queryset(self, **hints):
|
def get_queryset(self, **hints):
|
||||||
return self.field.remote_field.model._base_manager.db_manager(hints=hints).all()
|
return self.field.remote_field.model._base_manager.db_manager(hints=hints).all()
|
||||||
|
|
||||||
def get_prefetch_queryset(self, instances, queryset=None):
|
|
||||||
warnings.warn(
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
if queryset is None:
|
|
||||||
return self.get_prefetch_querysets(instances)
|
|
||||||
return self.get_prefetch_querysets(instances, [queryset])
|
|
||||||
|
|
||||||
def get_prefetch_querysets(self, instances, querysets=None):
|
def get_prefetch_querysets(self, instances, querysets=None):
|
||||||
if querysets and len(querysets) != 1:
|
if querysets and len(querysets) != 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@ -447,17 +433,6 @@ class ReverseOneToOneDescriptor:
|
|||||||
def get_queryset(self, **hints):
|
def get_queryset(self, **hints):
|
||||||
return self.related.related_model._base_manager.db_manager(hints=hints).all()
|
return self.related.related_model._base_manager.db_manager(hints=hints).all()
|
||||||
|
|
||||||
def get_prefetch_queryset(self, instances, queryset=None):
|
|
||||||
warnings.warn(
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
if queryset is None:
|
|
||||||
return self.get_prefetch_querysets(instances)
|
|
||||||
return self.get_prefetch_querysets(instances, [queryset])
|
|
||||||
|
|
||||||
def get_prefetch_querysets(self, instances, querysets=None):
|
def get_prefetch_querysets(self, instances, querysets=None):
|
||||||
if querysets and len(querysets) != 1:
|
if querysets and len(querysets) != 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@ -765,17 +740,6 @@ def create_reverse_many_to_one_manager(superclass, rel):
|
|||||||
queryset = super().get_queryset()
|
queryset = super().get_queryset()
|
||||||
return self._apply_rel_filters(queryset)
|
return self._apply_rel_filters(queryset)
|
||||||
|
|
||||||
def get_prefetch_queryset(self, instances, queryset=None):
|
|
||||||
warnings.warn(
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
if queryset is None:
|
|
||||||
return self.get_prefetch_querysets(instances)
|
|
||||||
return self.get_prefetch_querysets(instances, [queryset])
|
|
||||||
|
|
||||||
def get_prefetch_querysets(self, instances, querysets=None):
|
def get_prefetch_querysets(self, instances, querysets=None):
|
||||||
if querysets and len(querysets) != 1:
|
if querysets and len(querysets) != 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@ -1145,17 +1109,6 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
|
|||||||
queryset = super().get_queryset()
|
queryset = super().get_queryset()
|
||||||
return self._apply_rel_filters(queryset)
|
return self._apply_rel_filters(queryset)
|
||||||
|
|
||||||
def get_prefetch_queryset(self, instances, queryset=None):
|
|
||||||
warnings.warn(
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
if queryset is None:
|
|
||||||
return self.get_prefetch_querysets(instances)
|
|
||||||
return self.get_prefetch_querysets(instances, [queryset])
|
|
||||||
|
|
||||||
def get_prefetch_querysets(self, instances, querysets=None):
|
def get_prefetch_querysets(self, instances, querysets=None):
|
||||||
if querysets and len(querysets) != 1:
|
if querysets and len(querysets) != 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -33,7 +33,6 @@ from django.db.models.utils import (
|
|||||||
resolve_callables,
|
resolve_callables,
|
||||||
)
|
)
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
from django.utils.functional import cached_property, partition
|
from django.utils.functional import cached_property, partition
|
||||||
|
|
||||||
# The maximum number of results to fetch in a get() query.
|
# The maximum number of results to fetch in a get() query.
|
||||||
@ -2239,16 +2238,6 @@ class Prefetch:
|
|||||||
as_attr = self.to_attr and level == len(parts) - 1
|
as_attr = self.to_attr and level == len(parts) - 1
|
||||||
return to_attr, as_attr
|
return to_attr, as_attr
|
||||||
|
|
||||||
def get_current_queryset(self, level):
|
|
||||||
warnings.warn(
|
|
||||||
"Prefetch.get_current_queryset() is deprecated. Use "
|
|
||||||
"get_current_querysets() instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
querysets = self.get_current_querysets(level)
|
|
||||||
return querysets[0] if querysets is not None else None
|
|
||||||
|
|
||||||
def get_current_querysets(self, level):
|
def get_current_querysets(self, level):
|
||||||
if (
|
if (
|
||||||
self.get_current_prefetch_to(level) == self.prefetch_to
|
self.get_current_prefetch_to(level) == self.prefetch_to
|
||||||
@ -2480,11 +2469,7 @@ def get_prefetcher(instance, through_attr, to_attr):
|
|||||||
if rel_obj_descriptor:
|
if rel_obj_descriptor:
|
||||||
# singly related object, descriptor object has the
|
# singly related object, descriptor object has the
|
||||||
# get_prefetch_querysets() method.
|
# get_prefetch_querysets() method.
|
||||||
if (
|
if hasattr(rel_obj_descriptor, "get_prefetch_querysets"):
|
||||||
hasattr(rel_obj_descriptor, "get_prefetch_querysets")
|
|
||||||
# RemovedInDjango60Warning.
|
|
||||||
or hasattr(rel_obj_descriptor, "get_prefetch_queryset")
|
|
||||||
):
|
|
||||||
prefetcher = rel_obj_descriptor
|
prefetcher = rel_obj_descriptor
|
||||||
# If to_attr is set, check if the value has already been set,
|
# If to_attr is set, check if the value has already been set,
|
||||||
# which is done with has_to_attr_attribute(). Do not use the
|
# which is done with has_to_attr_attribute(). Do not use the
|
||||||
@ -2497,11 +2482,7 @@ def get_prefetcher(instance, through_attr, to_attr):
|
|||||||
# the attribute on the instance rather than the class to
|
# the attribute on the instance rather than the class to
|
||||||
# support many related managers
|
# support many related managers
|
||||||
rel_obj = getattr(instance, through_attr)
|
rel_obj = getattr(instance, through_attr)
|
||||||
if (
|
if hasattr(rel_obj, "get_prefetch_querysets"):
|
||||||
hasattr(rel_obj, "get_prefetch_querysets")
|
|
||||||
# RemovedInDjango60Warning.
|
|
||||||
or hasattr(rel_obj, "get_prefetch_queryset")
|
|
||||||
):
|
|
||||||
prefetcher = rel_obj
|
prefetcher = rel_obj
|
||||||
if through_attr == to_attr:
|
if through_attr == to_attr:
|
||||||
|
|
||||||
@ -2534,8 +2515,6 @@ def prefetch_one_level(instances, prefetcher, lookup, level):
|
|||||||
|
|
||||||
# The 'values to be matched' must be hashable as they will be used
|
# The 'values to be matched' must be hashable as they will be used
|
||||||
# in a dictionary.
|
# in a dictionary.
|
||||||
|
|
||||||
if hasattr(prefetcher, "get_prefetch_querysets"):
|
|
||||||
(
|
(
|
||||||
rel_qs,
|
rel_qs,
|
||||||
rel_obj_attr,
|
rel_obj_attr,
|
||||||
@ -2546,24 +2525,6 @@ def prefetch_one_level(instances, prefetcher, lookup, level):
|
|||||||
) = prefetcher.get_prefetch_querysets(
|
) = prefetcher.get_prefetch_querysets(
|
||||||
instances, lookup.get_current_querysets(level)
|
instances, lookup.get_current_querysets(level)
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
warnings.warn(
|
|
||||||
"The usage of get_prefetch_queryset() in prefetch_related_objects() is "
|
|
||||||
"deprecated. Implement get_prefetch_querysets() instead.",
|
|
||||||
RemovedInDjango60Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
queryset = None
|
|
||||||
if querysets := lookup.get_current_querysets(level):
|
|
||||||
queryset = querysets[0]
|
|
||||||
(
|
|
||||||
rel_qs,
|
|
||||||
rel_obj_attr,
|
|
||||||
instance_attr,
|
|
||||||
single,
|
|
||||||
cache_name,
|
|
||||||
is_descriptor,
|
|
||||||
) = prefetcher.get_prefetch_queryset(instances, queryset)
|
|
||||||
# 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
|
||||||
|
@ -286,6 +286,14 @@ to remove usage of these features.
|
|||||||
* The ``ChoicesMeta`` alias to ``django.db.models.enums.ChoicesType`` is
|
* The ``ChoicesMeta`` alias to ``django.db.models.enums.ChoicesType`` is
|
||||||
removed.
|
removed.
|
||||||
|
|
||||||
|
* The ``Prefetch.get_current_queryset()`` method is removed.
|
||||||
|
|
||||||
|
* The ``get_prefetch_queryset()`` method of related managers and descriptors is
|
||||||
|
removed.
|
||||||
|
|
||||||
|
* ``get_prefetcher()`` and ``prefetch_related_objects()`` no longer fallback to
|
||||||
|
``get_prefetch_queryset()``.
|
||||||
|
|
||||||
See :ref:`deprecated-features-5.1` for details on these changes, including how
|
See :ref:`deprecated-features-5.1` for details on these changes, including how
|
||||||
to remove usage of these features.
|
to remove usage of these features.
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ from django.contrib.contenttypes.prefetch import GenericPrefetch
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.utils import isolate_apps
|
from django.test.utils import isolate_apps
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
|
|
||||||
from .models import Answer, Post, Question
|
from .models import Answer, Post, Question
|
||||||
|
|
||||||
@ -99,29 +98,6 @@ class DeferredGenericRelationTests(TestCase):
|
|||||||
obj.question
|
obj.question
|
||||||
|
|
||||||
|
|
||||||
class GetPrefetchQuerySetDeprecation(TestCase):
|
|
||||||
def test_generic_relation_warning(self):
|
|
||||||
Question.objects.create(text="test")
|
|
||||||
questions = Question.objects.all()
|
|
||||||
msg = (
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead."
|
|
||||||
)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
questions[0].answer_set.get_prefetch_queryset(questions)
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
|
|
||||||
def test_generic_foreign_key_warning(self):
|
|
||||||
answers = Answer.objects.all()
|
|
||||||
msg = (
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead."
|
|
||||||
)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
Answer.question.get_prefetch_queryset(answers)
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
|
|
||||||
|
|
||||||
class GetPrefetchQuerySetsTests(TestCase):
|
class GetPrefetchQuerySetsTests(TestCase):
|
||||||
def test_duplicate_querysets(self):
|
def test_duplicate_querysets(self):
|
||||||
question = Question.objects.create(text="What is your name?")
|
question = Question.objects.create(text="What is your name?")
|
||||||
|
@ -2,7 +2,6 @@ from unittest import mock
|
|||||||
|
|
||||||
from django.db import connection, transaction
|
from django.db import connection, transaction
|
||||||
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
|
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Article,
|
Article,
|
||||||
@ -577,16 +576,6 @@ class ManyToManyTests(TestCase):
|
|||||||
)
|
)
|
||||||
self.assertIn("JOIN", ctx.captured_queries[0]["sql"])
|
self.assertIn("JOIN", ctx.captured_queries[0]["sql"])
|
||||||
|
|
||||||
def test_get_prefetch_queryset_warning(self):
|
|
||||||
articles = Article.objects.all()
|
|
||||||
msg = (
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead."
|
|
||||||
)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
self.a1.publications.get_prefetch_queryset(articles)
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
|
|
||||||
def test_get_prefetch_querysets_invalid_querysets_length(self):
|
def test_get_prefetch_querysets_invalid_querysets_length(self):
|
||||||
articles = Article.objects.all()
|
articles = Article.objects.all()
|
||||||
msg = (
|
msg = (
|
||||||
|
@ -4,7 +4,6 @@ from copy import deepcopy
|
|||||||
from django.core.exceptions import FieldError, MultipleObjectsReturned
|
from django.core.exceptions import FieldError, MultipleObjectsReturned
|
||||||
from django.db import IntegrityError, models, transaction
|
from django.db import IntegrityError, models, transaction
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
from django.utils.translation import gettext_lazy
|
from django.utils.translation import gettext_lazy
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
@ -887,29 +886,6 @@ class ManyToOneTests(TestCase):
|
|||||||
with self.assertRaisesMessage(TypeError, msg):
|
with self.assertRaisesMessage(TypeError, msg):
|
||||||
usa.cities.set([chicago.pk])
|
usa.cities.set([chicago.pk])
|
||||||
|
|
||||||
def test_get_prefetch_queryset_warning(self):
|
|
||||||
City.objects.create(name="Chicago")
|
|
||||||
cities = City.objects.all()
|
|
||||||
msg = (
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead."
|
|
||||||
)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
City.country.get_prefetch_queryset(cities)
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
|
|
||||||
def test_get_prefetch_queryset_reverse_warning(self):
|
|
||||||
usa = Country.objects.create(name="United States")
|
|
||||||
City.objects.create(name="Chicago")
|
|
||||||
countries = Country.objects.all()
|
|
||||||
msg = (
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead."
|
|
||||||
)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
usa.cities.get_prefetch_queryset(countries)
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
|
|
||||||
def test_get_prefetch_querysets_invalid_querysets_length(self):
|
def test_get_prefetch_querysets_invalid_querysets_length(self):
|
||||||
City.objects.create(name="Chicago")
|
City.objects.create(name="Chicago")
|
||||||
cities = City.objects.all()
|
cities = City.objects.all()
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from django.db import IntegrityError, connection, transaction
|
from django.db import IntegrityError, connection, transaction
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Bar,
|
Bar,
|
||||||
@ -606,16 +605,6 @@ class OneToOneTests(TestCase):
|
|||||||
self.b1.save()
|
self.b1.save()
|
||||||
self.assertEqual(self.b1.place, self.p2)
|
self.assertEqual(self.b1.place, self.p2)
|
||||||
|
|
||||||
def test_get_prefetch_queryset_warning(self):
|
|
||||||
places = Place.objects.all()
|
|
||||||
msg = (
|
|
||||||
"get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() "
|
|
||||||
"instead."
|
|
||||||
)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
Place.bar.get_prefetch_queryset(places)
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
|
|
||||||
def test_get_prefetch_querysets_invalid_querysets_length(self):
|
def test_get_prefetch_querysets_invalid_querysets_length(self):
|
||||||
places = Place.objects.all()
|
places = Place.objects.all()
|
||||||
msg = (
|
msg = (
|
||||||
|
@ -4,18 +4,15 @@ 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.fields.related import ForwardManyToOneDescriptor
|
from django.db.models.query import get_prefetcher
|
||||||
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,
|
||||||
)
|
)
|
||||||
from django.test.utils import CaptureQueriesContext
|
from django.test.utils import CaptureQueriesContext
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Article,
|
Article,
|
||||||
@ -2013,59 +2010,3 @@ class PrefetchLimitTests(TestDataMixin, TestCase):
|
|||||||
with self.subTest(book=book):
|
with self.subTest(book=book):
|
||||||
self.assertEqual(len(book.authors_sliced), 1)
|
self.assertEqual(len(book.authors_sliced), 1)
|
||||||
self.assertIn(book.authors_sliced[0], list(book.authors.all()))
|
self.assertIn(book.authors_sliced[0], list(book.authors.all()))
|
||||||
|
|
||||||
|
|
||||||
class DeprecationTests(TestCase):
|
|
||||||
def test_get_current_queryset_warning(self):
|
|
||||||
msg = (
|
|
||||||
"Prefetch.get_current_queryset() is deprecated. Use "
|
|
||||||
"get_current_querysets() instead."
|
|
||||||
)
|
|
||||||
authors = Author.objects.all()
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
self.assertEqual(
|
|
||||||
Prefetch("authors", authors).get_current_queryset(1),
|
|
||||||
authors,
|
|
||||||
)
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
|
|
||||||
self.assertIsNone(Prefetch("authors").get_current_queryset(1))
|
|
||||||
self.assertEqual(ctx.filename, __file__)
|
|
||||||
|
|
||||||
@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…
x
Reference in New Issue
Block a user