some performance optimizations

This commit is contained in:
Laura Klünder 2019-12-10 14:02:16 +01:00
parent dce93c3dd0
commit 35220eaef6
3 changed files with 29 additions and 7 deletions

View file

@ -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()}

View file

@ -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)

View file

@ -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().