Added fix to object.contents cache as well as reworked the extent of cache hooks on location modification.

This commit is contained in:
Griatch 2013-10-21 21:17:32 +02:00
parent 07af616b67
commit 06a0bea8d6
11 changed files with 125 additions and 653 deletions

View file

@ -97,27 +97,35 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg
update_fields = _GA(_GA(instance, "_meta"), "fields")
for field in update_fields:
fieldname = field.name
new_value = _GA(instance, fieldname)#field.value_from_object(instance)
# try to see if there is a handler on object that should be triggered when saving.
handlername = "_at_%s_save" % fieldname
handlername = "_at_%s_presave" % fieldname
handler = _GA(instance, handlername) if handlername in _GA(sender, '__dict__') else None
if callable(handler):
#hid = hashid(instance, "-%s" % fieldname)
try:
old_value = _GA(instance, _GA(field, "get_cache_name")())
except AttributeError:
old_value=None
# the handler may modify the stored value in various ways
# don't catch exceptions, the handler must work!
new_value = handler(new_value, old_value=old_value)
# we re-assign this to the field, save() will pick it up from there
_SA(instance, fieldname, new_value)
handler()
def field_post_save(sender, instance=None, update_fields=None, raw=False, **kwargs):
"""
Called at the beginning of the field save operation. The save method
must be called with the update_fields keyword in order to be most efficient.
This method should NOT save; rather it is the save() that triggers this function.
Its main purpose is to allow to plug-in a save handler and oob handlers.
"""
if raw:
return
if update_fields:
# this is a list of strings at this point. We want field objects
update_fields = (_GA(_GA(instance, "_meta"), "get_field_by_name")(field)[0] for field in update_fields)
else:
# meta.fields are already field objects; get them all
update_fields = _GA(_GA(instance, "_meta"), "fields")
for field in update_fields:
fieldname = field.name
handlername = "_at_%s_postsave" % fieldname
handler = _GA(instance, handlername) if handlername in _GA(sender, '__dict__') else None
if callable(handler):
handler()
trackerhandler = _GA(instance, "_trackerhandler") if "_trackerhandler" in _GA(instance, '__dict__') else None
if trackerhandler:
trackerhandler.update(fieldname, new_value)
#if hid:
# # update cache
# _FIELD_CACHE[hid] = new_value
trackerhandler.update(fieldname, _GA(instance, fieldname))
#------------------------------------------------------------
# Attr cache - caching the attribute objects related to a given object to
@ -125,63 +133,64 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg
# to any property).
#------------------------------------------------------------
# connected to m2m_changed signal in respective model class
def post_attr_update(sender, **kwargs):
"Called when the many2many relation changes (NOT when updating the value of an Attribute!)"
obj = kwargs['instance']
model = kwargs['model']
action = kwargs['action']
if kwargs['reverse']:
# the reverse relation changed (the Attribute itself was acted on)
pass
else:
# forward relation changed (the Object holding the Attribute m2m field)
if not kwargs["pk_set"]:
return
if action == "post_add":
# cache all added objects
for attr_id in kwargs["pk_set"]:
attr_obj = model.objects.get(pk=attr_id)
set_attr_cache(obj, _GA(attr_obj, "db_key"), attr_obj)
elif action == "post_remove":
# obj.db_attributes.remove(attr) was called
for attr_id in kwargs["pk_set"]:
attr_obj = model.objects.get(pk=attr_id)
del_attr_cache(obj, _GA(attr_obj, "db_key"))
attr_obj.delete()
elif action == "post_clear":
# obj.db_attributes.clear() was called
clear_obj_attr_cache(obj)
# access methods
def get_attr_cache(obj, attrname):
"Called by getting attribute"
hid = hashid(obj, "-%s" % attrname)
return _ATTR_CACHE.get(hid, None)
def set_attr_cache(obj, attrname, attrobj):
"Set the attr cache manually; this can be used to update"
global _ATTR_CACHE
hid = hashid(obj, "-%s" % attrname)
_ATTR_CACHE[hid] = attrobj
def del_attr_cache(obj, attrname):
"Del attribute cache"
global _ATTR_CACHE
hid = hashid(obj, "-%s" % attrname)
if hid in _ATTR_CACHE:
del _ATTR_CACHE[hid]
def flush_attr_cache():
"Clear attribute cache"
global _ATTR_CACHE
_ATTR_CACHE = {}
def clear_obj_attr_cache(obj):
global _ATTR_CACHE
hid = hashid(obj)
_ATTR_CACHE = {key:value for key, value in _ATTR_CACHE if not key.startswith(hid)}
## connected to m2m_changed signal in respective model class
#def post_attr_update(sender, **kwargs):
# "Called when the many2many relation changes (NOT when updating the value of an Attribute!)"
# obj = kwargs['instance']
# model = kwargs['model']
# action = kwargs['action']
# if kwargs['reverse']:
# # the reverse relation changed (the Attribute itself was acted on)
# pass
# else:
# # forward relation changed (the Object holding the Attribute m2m field)
# if not kwargs["pk_set"]:
# return
# if action == "post_add":
# # cache all added objects
# for attr_id in kwargs["pk_set"]:
# attr_obj = model.objects.get(pk=attr_id)
# set_attr_cache(obj, _GA(attr_obj, "db_key"), attr_obj)
# elif action == "post_remove":
# # obj.db_attributes.remove(attr) was called
# for attr_id in kwargs["pk_set"]:
# attr_obj = model.objects.get(pk=attr_id)
# del_attr_cache(obj, _GA(attr_obj, "db_key"))
# attr_obj.delete()
# elif action == "post_clear":
# # obj.db_attributes.clear() was called
# clear_obj_attr_cache(obj)
#
#
## attr cache - this is only left as deprecated cache
#
#def get_attr_cache(obj, attrname):
# "Called by getting attribute"
# hid = hashid(obj, "-%s" % attrname)
# return _ATTR_CACHE.get(hid, None)
#
#def set_attr_cache(obj, attrname, attrobj):
# "Set the attr cache manually; this can be used to update"
# global _ATTR_CACHE
# hid = hashid(obj, "-%s" % attrname)
# _ATTR_CACHE[hid] = attrobj
#
#def del_attr_cache(obj, attrname):
# "Del attribute cache"
# global _ATTR_CACHE
# hid = hashid(obj, "-%s" % attrname)
# if hid in _ATTR_CACHE:
# del _ATTR_CACHE[hid]
#
#def flush_attr_cache():
# "Clear attribute cache"
# global _ATTR_CACHE
# _ATTR_CACHE = {}
#
#def clear_obj_attr_cache(obj):
# global _ATTR_CACHE
# hid = hashid(obj)
# _ATTR_CACHE = {key:value for key, value in _ATTR_CACHE if not key.startswith(hid)}
#------------------------------------------------------------
# Property cache - this is a generic cache for properties stored on models.