summaryrefslogtreecommitdiff
path: root/tests/generic_relations
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/generic_relations
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/generic_relations')
-rw-r--r--tests/generic_relations/tests.py43
1 files changed, 42 insertions, 1 deletions
diff --git a/tests/generic_relations/tests.py b/tests/generic_relations/tests.py
index 1b53dbd8f4..3de243d7b8 100644
--- a/tests/generic_relations/tests.py
+++ b/tests/generic_relations/tests.py
@@ -1,7 +1,8 @@
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.prefetch import GenericPrefetch
-from django.core.exceptions import FieldError
+from django.core.exceptions import FieldError, FieldFetchBlocked
from django.db.models import Q, prefetch_related_objects
+from django.db.models.fetch_modes import FETCH_PEERS, RAISE
from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
from .models import (
@@ -780,6 +781,46 @@ class GenericRelationsTests(TestCase):
self.platypus.latin_name,
)
+ def test_fetch_mode_fetch_peers(self):
+ TaggedItem.objects.bulk_create(
+ [
+ TaggedItem(tag="lion", content_object=self.lion),
+ TaggedItem(tag="platypus", content_object=self.platypus),
+ TaggedItem(tag="quartz", content_object=self.quartz),
+ ]
+ )
+ # Peers fetching should fetch all related peers GFKs at once which is
+ # one query per content type.
+ with self.assertNumQueries(1):
+ quartz_tag, platypus_tag, lion_tag = TaggedItem.objects.fetch_mode(
+ FETCH_PEERS
+ ).order_by("-pk")[:3]
+ with self.assertNumQueries(2):
+ self.assertEqual(lion_tag.content_object, self.lion)
+ with self.assertNumQueries(0):
+ self.assertEqual(platypus_tag.content_object, self.platypus)
+ self.assertEqual(quartz_tag.content_object, self.quartz)
+ # It should ignore already cached instances though.
+ with self.assertNumQueries(1):
+ quartz_tag, platypus_tag, lion_tag = TaggedItem.objects.fetch_mode(
+ FETCH_PEERS
+ ).order_by("-pk")[:3]
+ with self.assertNumQueries(2):
+ self.assertEqual(quartz_tag.content_object, self.quartz)
+ self.assertEqual(lion_tag.content_object, self.lion)
+ with self.assertNumQueries(0):
+ self.assertEqual(platypus_tag.content_object, self.platypus)
+ self.assertEqual(quartz_tag.content_object, self.quartz)
+
+ def test_fetch_mode_raise(self):
+ TaggedItem.objects.create(tag="lion", content_object=self.lion)
+ tag = TaggedItem.objects.fetch_mode(RAISE).get(tag="yellow")
+ msg = "Fetching of TaggedItem.content_object blocked."
+ with self.assertRaisesMessage(FieldFetchBlocked, msg) as cm:
+ tag.content_object
+ self.assertIsNone(cm.exception.__cause__)
+ self.assertTrue(cm.exception.__suppress_context__)
+
class ProxyRelatedModelTest(TestCase):
def test_default_behavior(self):