import time from django.core.cache import cache from django.utils.http import http_date def cache_for_language(timeout=60, cache_key=None, func_args=None, cache_authenticated=False): """ Caches a view based on the users language code, a cache_key and optional function arguments. The cache_key can be a string, a callable or None. If it's None, the the name of the decorated function is used. You can pass a tuple `func_args` of arguments. If passed, these arguments are part of the cache key. See examples for details. It does not return a cached page if: - the user is authenticated - except you have set: cache_authenticated=True - the page was accessed through a POST request - the page has any GET arguments Example:: @cache_for_language(600, 'my_cache_key') def homepage(request) ... # cache_key is: en-us_my_cache_key @cache_for_language(600, 'my_cache_key', ('slug',)) def homepage(request, slug) ... # cache_key is: en-us_my_cache_key_a-slug-for-this @cache_for_language(600) def homepage(request, slug) ... # cache_key is: en-us_homepage def cache_name_func(request, *args, **kwargs): if request.user.is_authenticated: return request.user.username else: return 'public' @cache_for_language(600, cache_name_func, cache_authenticated=True) def homepage(request) ... # cache_key is: en-us_username # or if not auth: en-us_public """ def _cached(func): def do_cache(request, *args, **kwargs): # Deny caching on POST, GET-Arguments or user is authenticated allow_caching = not request.method == 'POST' \ and not request.GET.items() \ and (cache_authenticated or not request.user.is_authenticated()) if allow_caching: # Get string out of the cache key, if callable if callable(cache_key): funced_key = cache_key(request, *args, **kwargs) # or if it's a string, get this elif isinstance(cache_key, basestring): funced_key = cache_key # or use the function name as key else: funced_key = func.func_name # Collect key parts key_parts = [request.LANGUAGE_CODE, funced_key] if func_args: key_parts += [kwargs.get(f, '') for f in func_args] key = '_'.join(key_parts) # Fetch response from cache cached_repsonse = cache.get(key) if cached_repsonse: cached_repsonse['X-Cache'] = 'Hit' return cached_repsonse # Get real function response response = func(request, *args, **kwargs) response['X-Cache'] = 'None' # Set the cache if allow_caching: response['X-Cache-Time'] = http_date() response['X-Cache-Expires'] = http_date(time.time()+timeout) response['X-Cache-Key'] = key cache.set(key, response, timeout) response['X-Cache'] = 'Miss' return response return do_cache return _cached