summaryrefslogtreecommitdiff
path: root/tests/defer/tests.py
diff options
context:
space:
mode:
authorAdam Johnson <me@adamj.eu>2023-11-29 09:35:34 +0000
committerJacob Walls <jacobtylerwalls@gmail.com>2025-10-16 14:52:22 -0400
commite097e8a12f21a4e92594830f1ad1942b31916d0f (patch)
tree43f448bf968f0c6c1a48577cbc4d1ba5b920624a /tests/defer/tests.py
parentf6bd90c84050a1c74fe2161cced00e7282cb845c (diff)
Fixed #28586 -- Added model field fetch modes.
May your database queries be much reduced with minimal effort. co-authored-by: Andreas Pelme <andreas@pelme.se> co-authored-by: Simon Charette <charette.s@gmail.com> co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
Diffstat (limited to 'tests/defer/tests.py')
-rw-r--r--tests/defer/tests.py68
1 files changed, 65 insertions, 3 deletions
diff --git a/tests/defer/tests.py b/tests/defer/tests.py
index c0968080b1..29c63c566a 100644
--- a/tests/defer/tests.py
+++ b/tests/defer/tests.py
@@ -1,4 +1,5 @@
-from django.core.exceptions import FieldDoesNotExist, FieldError
+from django.core.exceptions import FieldDoesNotExist, FieldError, FieldFetchBlocked
+from django.db.models import FETCH_PEERS, RAISE
from django.test import SimpleTestCase, TestCase
from .models import (
@@ -29,6 +30,7 @@ class DeferTests(AssertionMixin, TestCase):
def setUpTestData(cls):
cls.s1 = Secondary.objects.create(first="x1", second="y1")
cls.p1 = Primary.objects.create(name="p1", value="xx", related=cls.s1)
+ cls.p2 = Primary.objects.create(name="p2", value="yy", related=cls.s1)
def test_defer(self):
qs = Primary.objects.all()
@@ -141,7 +143,6 @@ class DeferTests(AssertionMixin, TestCase):
def test_saving_object_with_deferred_field(self):
# Saving models with deferred fields is possible (but inefficient,
# since every field has to be retrieved first).
- Primary.objects.create(name="p2", value="xy", related=self.s1)
obj = Primary.objects.defer("value").get(name="p2")
obj.name = "a new name"
obj.save()
@@ -181,10 +182,71 @@ class DeferTests(AssertionMixin, TestCase):
self.assertEqual(obj.name, "adonis")
def test_defer_fk_attname(self):
- primary = Primary.objects.defer("related_id").get()
+ primary = Primary.objects.defer("related_id").get(name="p1")
with self.assertNumQueries(1):
self.assertEqual(primary.related_id, self.p1.related_id)
+ def test_only_fetch_mode_fetch_peers(self):
+ p1, p2 = Primary.objects.fetch_mode(FETCH_PEERS).only("name")
+ with self.assertNumQueries(1):
+ p1.value
+ with self.assertNumQueries(0):
+ p2.value
+
+ def test_only_fetch_mode_fetch_peers_single(self):
+ p1 = Primary.objects.fetch_mode(FETCH_PEERS).only("name").get(name="p1")
+ with self.assertNumQueries(1):
+ p1.value
+
+ def test_defer_fetch_mode_fetch_peers(self):
+ p1, p2 = Primary.objects.fetch_mode(FETCH_PEERS).defer("value")
+ with self.assertNumQueries(1):
+ p1.value
+ with self.assertNumQueries(0):
+ p2.value
+
+ def test_defer_fetch_mode_fetch_peers_single(self):
+ p1 = Primary.objects.fetch_mode(FETCH_PEERS).defer("value").get(name="p1")
+ with self.assertNumQueries(1):
+ p1.value
+
+ def test_only_fetch_mode_raise(self):
+ p1 = Primary.objects.fetch_mode(RAISE).only("name").get(name="p1")
+ msg = "Fetching of Primary.value blocked."
+ with self.assertRaisesMessage(FieldFetchBlocked, msg) as cm:
+ p1.value
+ self.assertIsNone(cm.exception.__cause__)
+ self.assertTrue(cm.exception.__suppress_context__)
+
+ def test_defer_fetch_mode_raise(self):
+ p1 = Primary.objects.fetch_mode(RAISE).defer("value").get(name="p1")
+ msg = "Fetching of Primary.value blocked."
+ with self.assertRaisesMessage(FieldFetchBlocked, msg) as cm:
+ p1.value
+ self.assertIsNone(cm.exception.__cause__)
+ self.assertTrue(cm.exception.__suppress_context__)
+
+
+class DeferOtherDatabaseTests(TestCase):
+ databases = {"other"}
+
+ @classmethod
+ def setUpTestData(cls):
+ cls.s1 = Secondary.objects.using("other").create(first="x1", second="y1")
+ cls.p1 = Primary.objects.using("other").create(
+ name="p1", value="xx", related=cls.s1
+ )
+ cls.p2 = Primary.objects.using("other").create(
+ name="p2", value="yy", related=cls.s1
+ )
+
+ def test_defer_fetch_mode_fetch_peers(self):
+ p1, p2 = Primary.objects.using("other").fetch_mode(FETCH_PEERS).defer("value")
+ with self.assertNumQueries(1, using="other"):
+ p1.value
+ with self.assertNumQueries(0, using="other"):
+ p2.value
+
class BigChildDeferTests(AssertionMixin, TestCase):
@classmethod