cache.py 2.12 KB
Newer Older
1 2 3 4
"""
This module aims to give a little more fine-tuned control of caching and cache
invalidation. Import these instead of django.core.cache.

5
Note that 'default' is being preserved for user session caching, which we're
6 7
not migrating so as not to inconvenience users by logging them all out.
"""
8 9
from functools import wraps

10 11
from django.core import cache

12

13 14 15 16
# If we can't find a 'general' CACHE defined in settings.py, we simply fall back
# to returning the default cache. This will happen with dev machines.
try:
    cache = cache.get_cache('general')
17
except Exception:
18 19
    cache = cache.cache

20

21 22 23
def cache_if_anonymous(view_func):
    """
    Many of the pages in edX are identical when the user is not logged
24 25 26
    in, but should not be cached when the user is logged in (because
    of the navigation bar at the top with the username).

27 28 29 30
    The django middleware cache does not handle this correctly, because
    we access the session to put the csrf token in the header. This adds
    the cookie to the vary header, and so every page is cached seperately
    for each user (because each user has a different csrf token).
31

32 33 34
    Note that this decorator should only be used on views that do not
    contain the csrftoken within the html. The csrf token can be included
    in the header by ordering the decorators as such:
35

36 37 38 39
    @ensure_csrftoken
    @cache_if_anonymous
    def myView(request):
    """
40

41 42 43 44
    @wraps(view_func)
    def _decorated(request, *args, **kwargs):
        if not request.user.is_authenticated():
            #Use the cache
45 46 47 48
            # same view accessed through different domain names may
            # return different things, so include the domain name in the key.
            domain = str(request.META.get('HTTP_HOST')) + '.'
            cache_key = domain + "cache_if_anonymous." + request.path
49 50 51 52
            response = cache.get(cache_key)
            if not response:
                response = view_func(request, *args, **kwargs)
                cache.set(cache_key, response, 60 * 3)
53

54
            return response
55

56 57 58
        else:
            #Don't use the cache
            return view_func(request, *args, **kwargs)
59

60
    return _decorated