summaryrefslogtreecommitdiff
path: root/django/db/models/base.py
diff options
context:
space:
mode:
authorKeryn Knight <keryn@kerynknight.com>2021-08-01 12:13:35 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-11-08 08:44:12 +0100
commit4f8c7fd9d91b35e2c2922de4bb50c8c8066cbbc6 (patch)
tree8852a9111b57708f644f9a792e1cd06597cdb61a /django/db/models/base.py
parentba9ced3e9a643a05bc521f0a2e6d02e3569de374 (diff)
Fixed #32980 -- Made models cache related managers.
Diffstat (limited to 'django/db/models/base.py')
-rw-r--r--django/db/models/base.py27
1 files changed, 23 insertions, 4 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index cc03ae1252..29bbde5e6b 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -382,11 +382,18 @@ class ModelBase(type):
return cls._meta.default_manager
-class ModelStateFieldsCacheDescriptor:
+class ModelStateCacheDescriptor:
+ """
+ Upon first access, replace itself with an empty dictionary on the instance.
+ """
+
+ def __set_name__(self, owner, name):
+ self.attribute_name = name
+
def __get__(self, instance, cls=None):
if instance is None:
return self
- res = instance.fields_cache = {}
+ res = instance.__dict__[self.attribute_name] = {}
return res
@@ -398,7 +405,20 @@ class ModelState:
# explicit (non-auto) PKs. This impacts validation only; it has no effect
# on the actual save.
adding = True
- fields_cache = ModelStateFieldsCacheDescriptor()
+ fields_cache = ModelStateCacheDescriptor()
+ related_managers_cache = ModelStateCacheDescriptor()
+
+ def __getstate__(self):
+ state = self.__dict__.copy()
+ if 'fields_cache' in state:
+ state['fields_cache'] = self.fields_cache.copy()
+ # Manager instances stored in related_managers_cache won't necessarily
+ # be deserializable if they were dynamically created via an inner
+ # scope, e.g. create_forward_many_to_many_manager() and
+ # create_generic_related_manager().
+ if 'related_managers_cache' in state:
+ state['related_managers_cache'] = {}
+ return state
class Model(metaclass=ModelBase):
@@ -552,7 +572,6 @@ class Model(metaclass=ModelBase):
"""Hook to allow choosing the attributes to pickle."""
state = self.__dict__.copy()
state['_state'] = copy.copy(state['_state'])
- state['_state'].fields_cache = state['_state'].fields_cache.copy()
return state
def __setstate__(self, state):