2 from django.core.cache import cache
3 from django.utils.functional import wraps
4 from cache_utils.utils import _cache_key, _func_info, _func_type
6 def cached(timeout, group=None):
7 """ Caching decorator. Can be applied to function, method or classmethod.
8 Supports bulk cache invalidation and invalidation for exact parameter
9 set. Cache keys are human-readable because they are constructed from
10 callable's full name and arguments and then sanitized to make
13 It can be used with or without group_backend. Without group_backend
14 bulk invalidation is not supported.
16 Wrapped callable gets `invalidate` methods. Call `invalidate` with
17 same arguments as function and the result for these arguments will be
21 backend_kwargs = {'group': group} if group else {}
25 func_type = _func_type(func)
28 def wrapper(*args, **kwargs):
30 # full name is stored as attribute on first call
31 if not hasattr(wrapper, '_full_name'):
32 name, _args = _func_info(func, args)
33 wrapper._full_name = name
35 # try to get the value from cache
36 key = _cache_key(wrapper._full_name, func_type, args, kwargs)
37 value = cache.get(key, **backend_kwargs)
39 # in case of cache miss recalculate the value and put it to the cache
41 value = func(*args, **kwargs)
42 cache.set(key, value, timeout, **backend_kwargs)
45 def invalidate(*args, **kwargs):
46 ''' invalidates cache result for function called with passed arguments '''
47 if not hasattr(wrapper, '_full_name'):
49 key = _cache_key(wrapper._full_name, 'function', args, kwargs)
50 cache.delete(key, **backend_kwargs)
52 wrapper.invalidate = invalidate