Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ answer newbie questions, and generally made Django that much better:
Marc Seguí Coll <metarizard@gmail.com>
Marc Tamlyn <marc.tamlyn@gmail.com>
Marc-Aurèle Brothier <ma.brothier@gmail.com>
Margaret Fero <maggiefero@gmail.com>
Marian Andre <django@andre.sk>
Marijke Luttekes <mail@marijkeluttekes.dev>
Marijn Vriens <marijn@metronomo.cl>
Expand Down
6 changes: 4 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ here's how we recommend you read the docs:
* See ``docs/README`` for instructions on building an HTML version of the docs.

Docs are updated rigorously. If you find any problems in the docs, or think
they should be clarified in any way, please take 30 seconds to fill out a
ticket here: https://code.djangoproject.com/newticket
they should be clarified in any way, please take 30 seconds to
`fill out a ticket <https://code.djangoproject.com/newticket>`_. You can log in
with your GitHub account, or with a DjangoProject account if you have one. Once
you log in, a New Ticket button is available next to View Tickets.

To get more help:

Expand Down
26 changes: 22 additions & 4 deletions django/db/models/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
resolve_callables,
)
from django.utils import timezone
from django.utils.deprecation import RemovedInDjango70Warning
from django.utils.deprecation import RemovedInDjango70Warning, RemovedInDjango71Warning
from django.utils.functional import cached_property
from django.utils.warnings import django_file_prefixes

Expand Down Expand Up @@ -577,18 +577,36 @@ def iterator(self, chunk_size=None):
)
return self._iterator(use_chunked_fetch, chunk_size)

async def aiterator(self, chunk_size=2000):
async def aiterator(self, chunk_size=None):
"""
An asynchronous iterator over the results from applying this QuerySet
to the database.
"""
if chunk_size <= 0:
if chunk_size is None:
if self._prefetch_related_lookups:
# RemovedInDjango71Warning: Replace the warning with:
# raise ValueError(
# "chunk_size must be provided when using "
# "QuerySet.aiterator() after prefetch_related()."
# )
warnings.warn(
"Using QuerySet.aiterator() after prefetch_related() without "
"providing a chunk_size is deprecated and will raise a "
"ValueError in Django 7.1.",
category=RemovedInDjango71Warning,
skip_file_prefixes=django_file_prefixes(),
)
# RemovedInDjango71Warning: When the deprecation ends, remove.
chunk_size = 2000
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"
)
iterable = self._iterable_class(
self, chunked_fetch=use_chunked_fetch, chunk_size=chunk_size
self,
chunked_fetch=use_chunked_fetch,
chunk_size=chunk_size or 2000,
)
if self._prefetch_related_lookups:
results = []
Expand Down
3 changes: 3 additions & 0 deletions docs/internals/deprecation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ details on these changes.

* The ``safe`` parameter of :class:`~django.http.JsonResponse` will be removed.

* Calling ``QuerySet.aiterator()`` after ``prefetch_related()`` without
providing a ``chunk_size`` will raise :exc:`ValueError`.

.. _deprecation-removed-in-7.0:

7.0
Expand Down
5 changes: 5 additions & 0 deletions docs/releases/6.2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,8 @@ Miscellaneous

* The ``safe`` parameter is deprecated from :class:`~django.http.JsonResponse`.
Omitting the argument is equivalent to the prior ``safe=False`` usage.

* Calling :meth:`.QuerySet.aiterator` after ``prefetch_related()`` without
providing a ``chunk_size`` is deprecated. It currently falls back to a
``chunk_size`` of 2000, but a ``ValueError`` will be raised in
Django 7.1.
24 changes: 23 additions & 1 deletion tests/async/test_async_queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.db import NotSupportedError, connection
from django.db.models import Prefetch, Sum
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
from django.utils.deprecation import RemovedInDjango71Warning

from .models import RelatedModel, SimpleModel

Expand Down Expand Up @@ -54,10 +55,31 @@ async def test_aiterator_prefetch_related(self):
results = []
async for s in SimpleModel.objects.prefetch_related(
Prefetch("relatedmodel_set", to_attr="prefetched_relatedmodel")
).aiterator():
).aiterator(chunk_size=2000):
results.append(s.prefetched_relatedmodel)
self.assertCountEqual(results, [[self.r1], [self.r2], [self.r3]])

async def test_aiterator_prefetch_related_chunk_size_none(self):
msg = (
"Using QuerySet.aiterator() after prefetch_related() without "
"providing a chunk_size is deprecated"
)
qs = SimpleModel.objects.prefetch_related("relatedmodel_set").aiterator()

# RemovedInDjango71Warning: When the deprecation ends, replace with:
# with self.assertRaisesMessage(
# ValueError,
# "chunk_size must be provided when using QuerySet.aiterator() "
# "after prefetch_related().",
# ):
# async for _ in qs:
# pass
results = []
with self.assertWarnsMessage(RemovedInDjango71Warning, msg):
async for s in qs:
results.append(s)
self.assertCountEqual(results, [self.s1, self.s2, self.s3])

async def test_aiterator_invalid_chunk_size(self):
msg = "Chunk size must be strictly positive."
for size in [0, -1]:
Expand Down
11 changes: 11 additions & 0 deletions tests/field_defaults/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ def test_both_default(self):
obj2 = DBDefaults.objects.create()
self.assertEqual(obj2.both, 1)

def test_db_default_blind_overwrite(self):
"""
Perform a blind overwrite: instantiate an object with a known pk
without fetching it, and overwrite some values. The db_default is used.
"""
obj1 = DBDefaults.objects.create(null=1.2)
unfetched_instance = DBDefaults(pk=obj1.pk)
unfetched_instance.save()
obj1.refresh_from_db()
self.assertEqual(obj1.null, 1.1)

def test_pk_db_default(self):
obj1 = DBDefaultsPK.objects.create()
if not connection.features.can_return_columns_from_insert:
Expand Down
Loading