summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2023-05-16 15:11:19 -0400
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-05-17 08:06:11 +0200
commit99e5dff737cd20b12d060e4794e097063b61ec40 (patch)
treeec5fadc1ec5d0972f879d6b22ca38a2856457aa7
parent0ec60661e61b153e6bcec64649b1b7f524eb3e18 (diff)
downloaddjango-99e5dff737cd20b12d060e4794e097063b61ec40.tar.gz
Fixed #34570 -- Silenced noop deferral of many-to-many and GFK.
While deferring many-to-many and GFK has no effect, the previous implementation of QuerySet.defer() ignore them instead of crashing. Regression in b3db6c8dcb5145f7d45eff517bcd96460475c879. Thanks Paco Martínez for the report.
-rw-r--r--django/db/models/sql/query.py10
-rw-r--r--docs/releases/4.2.2.txt4
-rw-r--r--tests/defer_regress/tests.py6
3 files changed, 19 insertions, 1 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index c8f849daea..252e5e9fcc 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -738,7 +738,15 @@ class Query(BaseExpression):
field_select_mask = select_mask.setdefault((field_name, relation), {})
field = relation.field
else:
- field = opts.get_field(field_name).field
+ reverse_rel = opts.get_field(field_name)
+ # While virtual fields such as many-to-many and generic foreign
+ # keys cannot be effectively deferred we've historically
+ # allowed them to be passed to QuerySet.defer(). Ignore such
+ # field references until a layer of validation at mask
+ # alteration time will be implemented eventually.
+ if not hasattr(reverse_rel, "field"):
+ continue
+ field = reverse_rel.field
field_select_mask = select_mask.setdefault(field, {})
related_model = field.model._meta.concrete_model
self._get_defer_select_mask(
diff --git a/docs/releases/4.2.2.txt b/docs/releases/4.2.2.txt
index a92582b7a0..ca21e5f1ec 100644
--- a/docs/releases/4.2.2.txt
+++ b/docs/releases/4.2.2.txt
@@ -15,3 +15,7 @@ Bugfixes
* Restored, following a regression in Django 4.2, ``get_prep_value()`` call in
``JSONField`` subclasses (:ticket:`34539`).
+
+* Fixed a regression in Django 4.2 that caused a crash of ``QuerySet.defer()``
+ when passing a ``ManyToManyField`` or ``GenericForeignKey`` reference. While
+ doing so is a no-op, it was allowed in older version (:ticket:`34570`).
diff --git a/tests/defer_regress/tests.py b/tests/defer_regress/tests.py
index 33193e187a..fc2d87e12b 100644
--- a/tests/defer_regress/tests.py
+++ b/tests/defer_regress/tests.py
@@ -271,6 +271,12 @@ class DeferRegressionTest(TestCase):
with self.assertNumQueries(1):
self.assertEqual(leaf.second_child.value, 64)
+ def test_defer_many_to_many_ignored(self):
+ location = Location.objects.create()
+ request = Request.objects.create(location=location)
+ with self.assertNumQueries(1):
+ self.assertEqual(Request.objects.defer("items").get(), request)
+
class DeferDeletionSignalsTests(TestCase):
senders = [Item, Proxy]