def __init__(self, cache=None): # {(InstanceInfo(instance).model_info.model, instance.pk): InstanceInfo, ...}} self._alive = WeakValueDictionary() # {InstanceInfo(instance): instance, ...}} self._dirty = {} if cache is not None: self._cache = cache else: self._cache = MRUCache(settings.MAX_CACHE) signals.register( ( "instance-deleted", "start-tracking-changes", "stop-tracking-changes", "model-pre-init", "model-post-init", "model-pre-save", "model-post-save", "model-pre-delete", "model-post-delete", "model-pre-update", "model-post-update", # "model-history-reset", # "model-history-redo", # "model-history-undo", "relation-pre-get", "relation-post-get", "relation-pre-set", "relation-post-set", "relation-pre-delete", "relation-post-delete", "relation-pre-add", "relation-post-add", "relation-pre-remove", "relation-post-remove", "model-do-cache", "model-do-not-cache", ), self ) signals.register_with_callback("cache-rollback", self, "rollback")
class Storage(object): def __init__(self, cache=None): # {(InstanceInfo(instance).model_info.model, instance.pk): InstanceInfo, ...}} self._alive = WeakValueDictionary() # {InstanceInfo(instance): instance, ...}} self._dirty = {} if cache is not None: self._cache = cache else: self._cache = MRUCache(settings.MAX_CACHE) signals.register( ( "instance-deleted", "start-tracking-changes", "stop-tracking-changes", "model-pre-init", "model-post-init", "model-pre-save", "model-post-save", "model-pre-delete", "model-post-delete", "model-pre-update", "model-post-update", # "model-history-reset", # "model-history-redo", # "model-history-undo", "relation-pre-get", "relation-post-get", "relation-pre-set", "relation-post-set", "relation-pre-delete", "relation-post-delete", "relation-pre-add", "relation-post-add", "relation-pre-remove", "relation-post-remove", "model-do-cache", "model-do-not-cache", ), self ) signals.register_with_callback("cache-rollback", self, "rollback") def get(self, query): return QuerySetIterator(query, self) def clear(self): self._dirty.clear() self._alive.clear() self._cache.clear() def set_dirty(self, inst_info): self._dirty[inst_info] = inst_info.get_inst() def cache(self, inf): self._alive.pop((inf.model_info.model, inf._lazypkval), None) self._alive[(inf.model_info.model, inf.get_pk_as_key())] = inf self._cache.add(inf) def uncache(self, inf): if inf in self._cache: self._cache.remove(inf) self._dirty.pop(inf, None) self._alive.pop((inf.model_info.model, inf.get_pk_as_key()), None) self._alive.pop((inf.model_info.model, inf._lazypkval), None) ### signals ### #??? what is this used for? def instance_deleted(self, inst_info): print "instance_deleted", inst_info def model_pre_init(self, instance, **kwargs): signals.fire("stop-tracking-changes", instance=instance) def model_post_init(self, instance, **kwargs): inf = get_inst_info(instance) signals.fire("start-tracking-changes", instance=instance) self._alive[(inf.model_info.model, inf.get_pk_as_key())] = inf # If instance was not initialized with a value for primary key, # then it has not been saved yet and goes into self._dirty. if instance.pk is None: self.set_dirty(inf) def start_tracking_changes(self, instance): get_inst_info(instance)._meta["track-changes"] = True def stop_tracking_changes(self, instance): get_inst_info(instance)._meta["track-changes"] = False def model_pre_save(self, instance): pass def model_post_save(self, instance, created): inf = get_inst_info(instance) if not inf._meta["do-cache"]: return self.cache(inf) self._dirty.pop(inf, None) # On calling Model.delete, tracking of changes is stopped, so start # tracking now. signals.fire("start-tracking-changes", instance=instance) def model_pre_update(self, instance, value, fieldname): # instance._inst_info.record_change(fieldname, value) pass def model_post_update(self, instance, value, fieldname): inf = get_inst_info(instance) if not inf in self._dirty: self.set_dirty(inf) def model_pre_delete(self, instance): signals.fire("stop-tracking-changes", instance=instance) def model_post_delete(self, instance, deleted): if not deleted: return inf = get_inst_info(instance) self.uncache(inf) instance.id = None def model_do_cache(self, instance): inf = get_inst_info(instance) self.cache(inf) self.set_dirty(inf) inf._meta["do-cache"] = True signals.fire("start-tracking-changes", instance=instance) def model_do_not_cache(self, instance): inf = get_inst_info(instance) self.uncache(inf) inf._meta["do-cache"] = False signals.fire("stop-tracking-changes", instance=instance) def model_history_reset(self, instance, **kwargs): raise NotImplementedError def model_history_undo(self, instance, fieldname, **kwargs): raise NotImplementedError def model_history_redo(self, instance, fieldname, **kwargs): raise NotImplementedError def relation_pre_get(self, manager, **kwargs): pass def relation_post_get(self, manager, **kwargs): pass def relation_pre_set(self, manager, values, **kwargs): pass def relation_post_set(self, manager, values, **kwargs): pass def relation_pre_delete(self, manager, **kwargs): pass def relation_post_delete(self, manager, **kwargs): pass def relation_pre_add(self, manager, values, **kwargs): pass def relation_post_add(self, manager, values, **kwargs): pass def relation_pre_remove(self, manager, values, **kwargs): pass def relation_post_remove(self, manager, values, **kwargs): pass