Browse Source

[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
Tim Bell 1 year ago
parent
commit
8b18e0bb3b
1 changed files with 13 additions and 0 deletions
  1. 13 0
      docs/ref/models/querysets.txt

+ 13 - 0
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.
+    <QuerySet [<Pizza: Hawaiian ()>, <Pizza: Seafood (prawns, smoked salmon)>]>
+
 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.