mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
This reverts4f8c7fd9d9and adds two regression tests: - test_related_manager_refresh(), and - test_create_copy_with_m2m(). Thanks joeli for the report. Backport of5e0aa362d9from main
This commit is contained in:
@@ -552,14 +552,6 @@ class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor):
|
||||
self.rel,
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def related_manager_cache_key(self):
|
||||
# By default, GenericRel instances will be marked as hidden unless
|
||||
# related_query_name is given (their accessor name being "+" when
|
||||
# hidden), which would cause multiple GenericRelations declared on a
|
||||
# single model to collide, so always use the remote field's name.
|
||||
return self.field.get_cache_name()
|
||||
|
||||
|
||||
def create_generic_related_manager(superclass, rel):
|
||||
"""
|
||||
|
||||
@@ -434,18 +434,11 @@ class ModelBase(type):
|
||||
return cls._meta.default_manager
|
||||
|
||||
|
||||
class ModelStateCacheDescriptor:
|
||||
"""
|
||||
Upon first access, replace itself with an empty dictionary on the instance.
|
||||
"""
|
||||
|
||||
def __set_name__(self, owner, name):
|
||||
self.attribute_name = name
|
||||
|
||||
class ModelStateFieldsCacheDescriptor:
|
||||
def __get__(self, instance, cls=None):
|
||||
if instance is None:
|
||||
return self
|
||||
res = instance.__dict__[self.attribute_name] = {}
|
||||
res = instance.fields_cache = {}
|
||||
return res
|
||||
|
||||
|
||||
@@ -458,20 +451,7 @@ class ModelState:
|
||||
# explicit (non-auto) PKs. This impacts validation only; it has no effect
|
||||
# on the actual save.
|
||||
adding = True
|
||||
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
|
||||
fields_cache = ModelStateFieldsCacheDescriptor()
|
||||
|
||||
|
||||
class Model(metaclass=ModelBase):
|
||||
@@ -633,6 +613,7 @@ 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()
|
||||
# memoryview cannot be pickled, so cast it to bytes and store
|
||||
# separately.
|
||||
_memoryview_attrs = []
|
||||
|
||||
@@ -561,14 +561,6 @@ class ReverseManyToOneDescriptor:
|
||||
self.rel = rel
|
||||
self.field = rel.field
|
||||
|
||||
@cached_property
|
||||
def related_manager_cache_key(self):
|
||||
# Being able to access the manager instance precludes it from being
|
||||
# hidden. The rel's accessor name is used to allow multiple managers
|
||||
# to the same model to coexist. e.g. post.attached_comment_set and
|
||||
# post.attached_link_set are separately cached.
|
||||
return self.rel.get_cache_name()
|
||||
|
||||
@cached_property
|
||||
def related_manager_cls(self):
|
||||
related_model = self.rel.related_model
|
||||
@@ -590,11 +582,8 @@ class ReverseManyToOneDescriptor:
|
||||
"""
|
||||
if instance is None:
|
||||
return self
|
||||
key = self.related_manager_cache_key
|
||||
instance_cache = instance._state.related_managers_cache
|
||||
if key not in instance_cache:
|
||||
instance_cache[key] = self.related_manager_cls(instance)
|
||||
return instance_cache[key]
|
||||
|
||||
return self.related_manager_cls(instance)
|
||||
|
||||
def _get_set_deprecation_msg_params(self):
|
||||
return (
|
||||
@@ -913,17 +902,6 @@ class ManyToManyDescriptor(ReverseManyToOneDescriptor):
|
||||
reverse=self.reverse,
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def related_manager_cache_key(self):
|
||||
if self.reverse:
|
||||
# Symmetrical M2Ms won't have an accessor name, but should never
|
||||
# end up in the reverse branch anyway, as the related_name ends up
|
||||
# being hidden, and no public manager is created.
|
||||
return self.rel.get_cache_name()
|
||||
else:
|
||||
# For forward managers, defer to the field name.
|
||||
return self.field.get_cache_name()
|
||||
|
||||
def _get_set_deprecation_msg_params(self):
|
||||
return (
|
||||
"%s side of a many-to-many set"
|
||||
|
||||
Reference in New Issue
Block a user