summaryrefslogtreecommitdiff
path: root/django/db/models/fetch_modes.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/fetch_modes.py')
-rw-r--r--django/db/models/fetch_modes.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/django/db/models/fetch_modes.py b/django/db/models/fetch_modes.py
new file mode 100644
index 0000000000..a22ccd8a23
--- /dev/null
+++ b/django/db/models/fetch_modes.py
@@ -0,0 +1,52 @@
+from django.core.exceptions import FieldFetchBlocked
+
+
+class FetchMode:
+ __slots__ = ()
+
+ track_peers = False
+
+ def fetch(self, fetcher, instance):
+ raise NotImplementedError("Subclasses must implement this method.")
+
+
+class FetchOne(FetchMode):
+ __slots__ = ()
+
+ def fetch(self, fetcher, instance):
+ fetcher.fetch_one(instance)
+
+
+FETCH_ONE = FetchOne()
+
+
+class FetchPeers(FetchMode):
+ __slots__ = ()
+
+ track_peers = True
+
+ def fetch(self, fetcher, instance):
+ instances = [
+ peer
+ for peer_weakref in instance._state.peers
+ if (peer := peer_weakref()) is not None
+ ]
+ if len(instances) > 1:
+ fetcher.fetch_many(instances)
+ else:
+ fetcher.fetch_one(instance)
+
+
+FETCH_PEERS = FetchPeers()
+
+
+class Raise(FetchMode):
+ __slots__ = ()
+
+ def fetch(self, fetcher, instance):
+ klass = instance.__class__.__qualname__
+ field_name = fetcher.field.name
+ raise FieldFetchBlocked(f"Fetching of {klass}.{field_name} blocked.") from None
+
+
+RAISE = Raise()