Login

Language aware cache decorator

Author:
bartTC
Posted:
April 28, 2009
Language:
Python
Version:
1.0
Score:
2 (after 2 ratings)

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

Please login first before commenting.