mirror of
https://github.com/django/django.git
synced 2025-10-29 00:26:07 +00:00
Fixed #29984 -- Added QuerySet.iterator() support for prefetching related objects.
Co-authored-by: Raphael Kimmig <raphael.kimmig@ampad.de> Co-authored-by: Simon Charette <charette.s@gmail.com>
This commit is contained in:
committed by
Mariusz Felisiak
parent
c27932ec93
commit
edbf930287
@@ -5,7 +5,7 @@ The main QuerySet implementation. This provides the public API for the ORM.
|
||||
import copy
|
||||
import operator
|
||||
import warnings
|
||||
from itertools import chain
|
||||
from itertools import chain, islice
|
||||
|
||||
import django
|
||||
from django.conf import settings
|
||||
@@ -23,6 +23,7 @@ from django.db.models.query_utils import FilteredRelation, Q
|
||||
from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE
|
||||
from django.db.models.utils import create_namedtuple_class, resolve_callables
|
||||
from django.utils import timezone
|
||||
from django.utils.deprecation import RemovedInDjango50Warning
|
||||
from django.utils.functional import cached_property, partition
|
||||
|
||||
# The maximum number of results to fetch in a get() query.
|
||||
@@ -356,14 +357,40 @@ class QuerySet:
|
||||
####################################
|
||||
|
||||
def _iterator(self, use_chunked_fetch, chunk_size):
|
||||
yield from self._iterable_class(self, chunked_fetch=use_chunked_fetch, chunk_size=chunk_size)
|
||||
iterable = self._iterable_class(
|
||||
self,
|
||||
chunked_fetch=use_chunked_fetch,
|
||||
chunk_size=chunk_size or 2000,
|
||||
)
|
||||
if not self._prefetch_related_lookups or chunk_size is None:
|
||||
yield from iterable
|
||||
return
|
||||
|
||||
def iterator(self, chunk_size=2000):
|
||||
iterator = iter(iterable)
|
||||
while results := list(islice(iterator, chunk_size)):
|
||||
prefetch_related_objects(results, *self._prefetch_related_lookups)
|
||||
yield from results
|
||||
|
||||
def iterator(self, chunk_size=None):
|
||||
"""
|
||||
An iterator over the results from applying this QuerySet to the
|
||||
database.
|
||||
database. chunk_size must be provided for QuerySets that prefetch
|
||||
related objects. Otherwise, a default chunk_size of 2000 is supplied.
|
||||
"""
|
||||
if chunk_size <= 0:
|
||||
if chunk_size is None:
|
||||
if self._prefetch_related_lookups:
|
||||
# When the deprecation ends, replace with:
|
||||
# raise ValueError(
|
||||
# 'chunk_size must be provided when using '
|
||||
# 'QuerySet.iterator() after prefetch_related().'
|
||||
# )
|
||||
warnings.warn(
|
||||
'Using QuerySet.iterator() after prefetch_related() '
|
||||
'without specifying chunk_size is deprecated.',
|
||||
category=RemovedInDjango50Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
elif chunk_size <= 0:
|
||||
raise ValueError('Chunk size must be strictly positive.')
|
||||
use_chunked_fetch = not connections[self.db].settings_dict.get('DISABLE_SERVER_SIDE_CURSORS')
|
||||
return self._iterator(use_chunked_fetch, chunk_size)
|
||||
|
||||
Reference in New Issue
Block a user