fromdjango.core.cacheimportcachefromfunctoolsimportwrapsimportcopydefmake_hash(obj):"""Make a hash from an arbitrary nested dictionary, list, tuple or set. """ifisinstance(obj,set)orisinstance(obj,tuple)orisinstance(obj,list):returnhash(tuple([make_hash(e)foreinobj]))elifnotisinstance(obj,dict):returnhash(obj)new_obj=copy.deepcopy(obj)fork,vinnew_obj.items():new_obj[k]=make_hash(v)returnhash(tuple(frozenset(new_obj.items())))defcached(function,hours=1):"""Return a version of this function that caches its results for the time specified. >>> def foo(x): print "called"; return 1 >>> cached(foo)('whatever') called 1 >>> cached(foo)('whatever') 1 """@wraps(function)defget_cache_or_call(*args,**kwargs):# known bug: if the function returns None, we never save it in# the cachecache_key=make_hash((function.__module__+function.__name__,args,kwargs))cached_result=cache.get(cache_key)ifcached_resultisNone:result=function(*args)cache.set(cache_key,result,60*60*hours)returnresultelse:returncached_resultreturnget_cache_or_call