def runTest(self): # Create some Movie data-sets. terminator = Movie(title="Terminator 2") inf = get_inst_info(terminator) # Before an instance is saved it is put in the QuerySet's # store. It has to be in either store._dirty or store._cache # to be kept alive. self.assert_(terminator is store._alive[(inf.model_info.model, inf.get_pk_as_key())].get_inst()) # ... and marked dirty (i.e. altered, unsaved). self.assert_(terminator is store._dirty[inf]) # It has not been put in the database store yet self.assert_(terminator not in store._cache._instances.values()) # Now save. terminator.save() # Instance is still an alive (in-memory) object self.assert_(terminator is store._alive[(inf.model_info.model, inf.get_pk_as_key())].get_inst()) self.assert_(len(store._alive) == 1) # Instance is not dirty anymore ... self.assert_(not store._dirty) # ... and is now in the database store. self.assert_(terminator in store._cache._instances.values()) self.assert_(terminator is store._cache._instances[inf]) self.assert_(len(store._cache._instances) == 1)
def model_post_delete(self, instance, deleted): if not deleted: return inf = get_inst_info(instance) self.uncache(inf) instance.id = None
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 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 __set__(self, inst, val): inst_info = get_inst_info(inst) if inst_info._meta["track-changes"]: signals.fire("model-pre-update", instance=inst, value=inst_info.get(self.name), fieldname=self.name) field = type(inst).fields()[self.name] val = field.to_python(val) inst_info[field.column_name] = val if inst_info._meta["track-changes"]: signals.fire("model-post-update", instance=inst, value=val, fieldname=self.name)
def _gen(self, start=None, stop=None, step=None): start, stop, step = start or 0, stop or sys.maxint, step or 1 aliases = self.query.get_selection_aliases() pkcol = self.query.model.pk.column_name ## Save all dirty instances to get consistent results. for obj in self.store._dirty.values(): obj.save() for row in self.query.execute().fetchall()[start:stop:step]: vars = dict(zip(aliases, row)) if not (self.query.model, vars[pkcol]) in self.store._alive: inst = self.query.model(**vars) inf = get_inst_info(inst) else: inf = self.store._alive[(self.query.model, vars[pkcol])] if inf.get_inst() is None: ## Initializing a new instance with __init__ automatically ## sets a new InstanceInfo instance which is not useful ## here, since the instance info already exists. inst = object.__new__(inf.model_info.model) inf.set_inst(inst) inf._meta["was-reloaded"] = True if inf._meta["was-reloaded"] or inf._meta["force-sync"]: inf.update(vars) self.store._cache.add(inf) yield inf.get_inst() # Remove any objects in this process that were deleted in other # processes. else: # Delete all self.query.model instances from the cache. # There is probably a more efficient way of cleaning the # cache (more selectively), but it seems not worth the # effort atm. for m, pk in self.store._alive.keys(): if isinstance(m, self.query.model): inf = self.store._alive[(m, pk)] if inf.get_inst() is not None: signals.fire("model-pre-delete", inf.get_inst(), True) signals.fire("model-post-delete", inf.get_inst(), True)
def runTest(self): # Create some Movie data-sets. terminator = Movie(title="Terminator 2") terminator.save() totalrecall, created, = Movie(title="Total Recall").save() twins, created = Movie(title="Twins").save() movies = Movie.objects.all() # evaluate the query, hit the store/database. movies_list = list(movies) # the instances have been set as expected. self.assert_([terminator, totalrecall, twins] == movies_list) self.assert_(set(movies) == set(store._cache._instances.values())) # now make a QuerySet for only one instance of the above Movie instances. fltrqs = Movie.objects.filter(title__contains="Term") # now eval it. term_movies = list(fltrqs) # see if the instances have been set as expected. self.assert_([terminator] == term_movies) # misc inf = get_inst_info(terminator) self.assert_(list(fltrqs)[0] is terminator) self.assert_(store._cache._instances[inf] is terminator) # add a little confusion ... list(movies) self.assert_(list(fltrqs)[0] is terminator is movies[0]) # after all this experimenting, make sure there are no excess instances # in the store self.assert_(len(store._cache._instances) == 3)
def __get__(self, inst, cls): if inst is None: raise Exception("no access of %s via class!" %self) return get_inst_info(inst).get(self.name)
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_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_post_update(self, instance, value, fieldname): inf = get_inst_info(instance) if not inf in self._dirty: self.set_dirty(inf)
def stop_tracking_changes(self, instance): get_inst_info(instance)._meta["track-changes"] = False
def start_tracking_changes(self, instance): get_inst_info(instance)._meta["track-changes"] = True