1. Mikhail Korobov
  2. django-cache-utils

Source

django-cache-utils / cache_utils / decorators.py

Mikhail Korobov 0adb40c 


Mikhail Korobov 96fa235 
Mikhail Korobov 0adb40c 


Mikhail Korobov 1312ac9 










Mikhail Korobov 0adb40c 

Mikhail Korobov 4b3ea78 

Mikhail Korobov 0adb40c 

Mikhail Korobov 96fa235 
Mikhail Korobov 0adb40c 



Mikhail Korobov 96fa235 




Mikhail Korobov 0adb40c 
Mikhail Korobov 96fa235 
Mikhail Korobov 4b3ea78 
Mikhail Korobov 0adb40c 



Mikhail Korobov 4b3ea78 
Mikhail Korobov 0adb40c 
Mikhail Korobov 1312ac9 
Mikhail Korobov 96fa235 




Mikhail Korobov 1312ac9 
Mikhail Korobov 0adb40c 
#coding: utf-8
from django.core.cache import cache
from django.utils.functional import wraps
from cache_utils.utils import _cache_key, _func_info, _func_type

def cached(timeout, group=None):
    """ Caching decorator. Can be applied to function, method or classmethod.
    Supports bulk cache invalidation and invalidation for exact parameter
    set. Cache keys are human-readable because they are constructed from
    callable's full name and arguments and then sanitized to make
    memcached happy.

    It can be used with or without group_backend. Without group_backend
    bulk invalidation is not supported.

    Wrapped callable gets `invalidate` methods. Call `invalidate` with
    same arguments as function and the result for these arguments will be
    invalidated.
    """

    backend_kwargs = {'group': group} if group else {}

    def _cached(func):

        func_type = _func_type(func)

        @wraps(func)
        def wrapper(*args, **kwargs):

            # full name is stored as attribute on first call
            if not hasattr(wrapper, '_full_name'):
                name, _args = _func_info(func, args)
                wrapper._full_name = name

            # try to get the value from cache
            key = _cache_key(wrapper._full_name, func_type, args, kwargs)
            value = cache.get(key, **backend_kwargs)

            # in case of cache miss recalculate the value and put it to the cache
            if value is None:
                value = func(*args, **kwargs)
                cache.set(key, value, timeout, **backend_kwargs)
            return value

        def invalidate(*args, **kwargs):
            ''' invalidates cache result for function called with passed arguments '''
            key = _cache_key(wrapper._full_name, 'function', args, kwargs)
            cache.delete(key, **backend_kwargs)

        wrapper.invalidate = invalidate
        return wrapper
    return _cached