mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
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>
This commit is contained in:
committed by
Jacob Walls
parent
f6bd90c840
commit
e097e8a12f
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user