some performance optimizations
This commit is contained in:
parent
dce93c3dd0
commit
35220eaef6
3 changed files with 29 additions and 7 deletions
|
@ -42,8 +42,7 @@ class ChangedObject(models.Model):
|
||||||
unique_together = ('changeset', 'content_type', 'existing_object_pk')
|
unique_together = ('changeset', 'content_type', 'existing_object_pk')
|
||||||
ordering = ['created', 'pk']
|
ordering = ['created', 'pk']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, model_class=None, **kwargs):
|
||||||
model_class = kwargs.pop('model_class', None)
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._set_object = None
|
self._set_object = None
|
||||||
self._m2m_added_cache = {name: set(values) for name, values in self.m2m_added.items()}
|
self._m2m_added_cache = {name: set(values) for name, values in self.m2m_added.items()}
|
||||||
|
|
|
@ -75,6 +75,14 @@ class ChangeSet(models.Model):
|
||||||
|
|
||||||
self.direct_editing = False
|
self.direct_editing = False
|
||||||
|
|
||||||
|
self._wrapped_model_cache = {}
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
return {
|
||||||
|
**self.__dict__,
|
||||||
|
'_wrapped_model_cache': {}
|
||||||
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Get Changesets for Request/Session/User
|
Get Changesets for Request/Session/User
|
||||||
"""
|
"""
|
||||||
|
@ -138,13 +146,20 @@ class ChangeSet(models.Model):
|
||||||
if self.direct_editing:
|
if self.direct_editing:
|
||||||
model.EditorForm = ModelWrapper(self, model).EditorForm
|
model.EditorForm = ModelWrapper(self, model).EditorForm
|
||||||
return model
|
return model
|
||||||
return ModelWrapper(self, model)
|
return self._get_wrapped_model(model)
|
||||||
|
|
||||||
|
def _get_wrapped_model(self, model):
|
||||||
|
wrapped = self._wrapped_model_cache.get(model, None)
|
||||||
|
if wrapped is None:
|
||||||
|
wrapped = ModelWrapper(self, model)
|
||||||
|
self._wrapped_model_cache[model] = wrapped
|
||||||
|
return wrapped
|
||||||
|
|
||||||
def wrap_instance(self, instance):
|
def wrap_instance(self, instance):
|
||||||
assert isinstance(instance, models.Model)
|
assert isinstance(instance, models.Model)
|
||||||
if self.direct_editing:
|
if self.direct_editing:
|
||||||
return instance
|
return instance
|
||||||
return self.wrap_model(instance.__class__).create_wrapped_model_class()(self, instance)
|
return self.wrap_model(instance.__class__).wrapped_model_class(self, instance)
|
||||||
|
|
||||||
def relevant_changed_objects(self) -> typing.Iterable[ChangedObject]:
|
def relevant_changed_objects(self) -> typing.Iterable[ChangedObject]:
|
||||||
return self.changed_objects_set.exclude(existing_object_pk__isnull=True, deleted=True)
|
return self.changed_objects_set.exclude(existing_object_pk__isnull=True, deleted=True)
|
||||||
|
|
|
@ -42,7 +42,7 @@ class BaseWrapper:
|
||||||
return model
|
return model
|
||||||
model = model._obj
|
model = model._obj
|
||||||
assert issubclass(model, models.Model)
|
assert issubclass(model, models.Model)
|
||||||
return ModelWrapper(self._changeset, model)
|
return self._changeset._get_wrapped_model(model)
|
||||||
|
|
||||||
def _wrap_instance(self, instance):
|
def _wrap_instance(self, instance):
|
||||||
"""
|
"""
|
||||||
|
@ -53,7 +53,7 @@ class BaseWrapper:
|
||||||
return instance
|
return instance
|
||||||
instance = instance._obj
|
instance = instance._obj
|
||||||
assert isinstance(instance, models.Model)
|
assert isinstance(instance, models.Model)
|
||||||
return self._wrap_model(instance.__class__).create_wrapped_model_class()(self._changeset, instance)
|
return self._wrap_model(instance.__class__).wrapped_model_class(self._changeset, instance)
|
||||||
|
|
||||||
def _wrap_manager(self, manager):
|
def _wrap_manager(self, manager):
|
||||||
"""
|
"""
|
||||||
|
@ -133,12 +133,16 @@ class ModelWrapper(BaseWrapper):
|
||||||
"""
|
"""
|
||||||
return get_submodels(self._obj)
|
return get_submodels(self._obj)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def wrapped_model_class(self) -> typing.Type['ModelInstanceWrapper']:
|
||||||
|
return self.create_wrapped_model_class()
|
||||||
|
|
||||||
def create_wrapped_model_class(self) -> typing.Type['ModelInstanceWrapper']:
|
def create_wrapped_model_class(self) -> typing.Type['ModelInstanceWrapper']:
|
||||||
"""
|
"""
|
||||||
Return a ModelInstanceWrapper that has a proxy to this instance as its type / metaclass. #voodoo
|
Return a ModelInstanceWrapper that has a proxy to this instance as its type / metaclass. #voodoo
|
||||||
"""
|
"""
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return self.create_metaclass()(self._obj.__name__ + 'InstanceWrapper', (ModelInstanceWrapper,), {})
|
return self.metaclass(self._obj.__name__ + 'InstanceWrapper', (ModelInstanceWrapper,), {})
|
||||||
|
|
||||||
def __call__(self, **kwargs):
|
def __call__(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -149,6 +153,10 @@ class ModelWrapper(BaseWrapper):
|
||||||
setattr(instance, name, value)
|
setattr(instance, name, value)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def metaclass(self):
|
||||||
|
return self.create_metaclass()
|
||||||
|
|
||||||
def create_metaclass(self):
|
def create_metaclass(self):
|
||||||
"""
|
"""
|
||||||
Create the proxy metaclass for craeate_wrapped_model_class().
|
Create the proxy metaclass for craeate_wrapped_model_class().
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue