summaryrefslogtreecommitdiff
path: root/django/db/models/base.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 /django/db/models/base.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 'django/db/models/base.py')
-rw-r--r--django/db/models/base.py25
1 files changed, 22 insertions, 3 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index fd51052d01..b92a198660 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -32,6 +32,7 @@ from django.db.models import NOT_PROVIDED, ExpressionWrapper, IntegerField, Max,
from django.db.models.constants import LOOKUP_SEP
from django.db.models.deletion import CASCADE, Collector
from django.db.models.expressions import DatabaseDefault
+from django.db.models.fetch_modes import FETCH_ONE
from django.db.models.fields.composite import CompositePrimaryKey
from django.db.models.fields.related import (
ForeignObjectRel,
@@ -466,6 +467,14 @@ class ModelStateFieldsCacheDescriptor:
return res
+class ModelStateFetchModeDescriptor:
+ def __get__(self, instance, cls=None):
+ if instance is None:
+ return self
+ res = instance.fetch_mode = FETCH_ONE
+ return res
+
+
class ModelState:
"""Store model instance state."""
@@ -476,6 +485,14 @@ class ModelState:
# on the actual save.
adding = True
fields_cache = ModelStateFieldsCacheDescriptor()
+ fetch_mode = ModelStateFetchModeDescriptor()
+ peers = ()
+
+ def __getstate__(self):
+ state = self.__dict__.copy()
+ # Weak references can't be pickled.
+ state.pop("peers", None)
+ return state
class Model(AltersData, metaclass=ModelBase):
@@ -595,7 +612,7 @@ class Model(AltersData, metaclass=ModelBase):
post_init.send(sender=cls, instance=self)
@classmethod
- def from_db(cls, db, field_names, values):
+ def from_db(cls, db, field_names, values, *, fetch_mode=None):
if len(values) != len(cls._meta.concrete_fields):
values_iter = iter(values)
values = [
@@ -605,6 +622,8 @@ class Model(AltersData, metaclass=ModelBase):
new = cls(*values)
new._state.adding = False
new._state.db = db
+ if fetch_mode is not None:
+ new._state.fetch_mode = fetch_mode
return new
def __repr__(self):
@@ -714,8 +733,8 @@ class Model(AltersData, metaclass=ModelBase):
should be an iterable of field attnames. If fields is None, then
all non-deferred fields are reloaded.
- When accessing deferred fields of an instance, the deferred loading
- of the field will call this method.
+ When fetching deferred fields for a single instance (the FETCH_ONE
+ fetch mode), the deferred loading uses this method.
"""
if fields is None:
self._prefetched_objects_cache = {}