From 8b18e0bb3ba8bb1f51e15487a6d5402853e637ae Mon Sep 17 00:00:00 2001 From: Tim Bell Date: Fri, 20 Oct 2023 14:37:19 -0400 Subject: [PATCH] [5.0.x] Fixed #27403 -- Doc'd that QuerySet.prefetch_related() doesn't guarantee transactional consistency. Added a note about the potential race condition in prefetch_related() that could produce an inconsistent result, one that does not correspond to any point in the database history. Backport of ee104251c403fbac83b8475163ff2ac01c567d25 from main --- docs/ref/models/querysets.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index fc1c5571e0..99feac4318 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -1211,6 +1211,19 @@ results; these ``QuerySets`` are then used in the ``self.toppings.all()`` calls. The additional queries in ``prefetch_related()`` are executed after the ``QuerySet`` has begun to be evaluated and the primary query has been executed. +Note that there is no mechanism to prevent another database query from altering +the items in between the execution of the primary query and the additional +queries, which could produce an inconsistent result. For example, if a +``Pizza`` is deleted after the primary query has executed, its toppings will +not be returned in the additional query, and it will seem like the pizza has no +toppings: + +.. code-block:: pycon + + >>> Pizza.objects.prefetch_related("toppings") + # "Hawaiian" Pizza was deleted in another shell. + , ]> + If you have an iterable of model instances, you can prefetch related attributes on those instances using the :func:`~django.db.models.prefetch_related_objects` function.