Ticket #612: cache-control.diff

File cache-control.diff, 5.2 KB (added by hugo, 19 years ago)

Cache-Control managing decorator and function

  • django/utils/cache.py

     
    2121from django.conf import settings
    2222from django.core.cache import cache
    2323
     24cc_delim_re = re.compile(r'\s*,\s*')
     25def patch_cache_control(response, **kwargs):
     26    """
     27    This function patches the Cache-Control header by adding all
     28    keyword arguments to it. The transformation is as follows:
     29
     30    - all keyword parameter names are turned to lowercase and
     31      all _ will be translated to -
     32    - if the value of a parameter is True (exatly True, not just a
     33      true value), only the parameter name is added to the header
     34    - all other parameters are added with their value, after applying
     35      str to it.
     36    """
     37
     38    def dictitem(s):
     39        t = s.split('=',1)
     40        if len(t) > 1:
     41            return (t[0].lower().replace('-', '_'), t[1])
     42        else:
     43            return (t[0].lower().replace('-', '_'), True)
     44
     45    def dictvalue(t):
     46        if t[1] == True:
     47            return t[0]
     48        else:
     49            return t[0] + '=' + str(t[1])
     50
     51    if response.has_header('Cache-Control'):
     52        print response['Cache-Control']
     53        cc = cc_delim_re.split(response['Cache-Control'])
     54        print cc
     55        cc = dict([dictitem(el) for el in cc])
     56    else:
     57        cc = {}
     58    for (k,v) in kwargs.items():
     59        cc[k.replace('_', '-')] = v
     60    cc = ', '.join([dictvalue(el) for el in cc.items()])
     61    response['Cache-Control'] = cc
     62
    2463vary_delim_re = re.compile(r',\s*')
    2564
    2665def patch_response_headers(response, cache_timeout=None):
     
    4382        response['Last-Modified'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT')
    4483    if not response.has_header('Expires'):
    4584        response['Expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S GMT')
    46     if not response.has_header('Cache-Control'):
    47         response['Cache-Control'] = 'max-age=%d' % cache_timeout
     85    patch_cache_control(response, max_age=cache_timeout)
    4886
    4987def patch_vary_headers(response, newheaders):
    5088    """
  • django/views/decorators/cache.py

     
    1010Additionally, all headers from the response's Vary header will be taken into
    1111account on caching -- just like the middleware does.
    1212"""
     13import re
    1314
    1415from django.utils.decorators import decorator_from_middleware
     16from django.utils.cache import patch_cache_control
    1517from django.middleware.cache import CacheMiddleware
    1618
    1719cache_page = decorator_from_middleware(CacheMiddleware)
     20
     21def cache_control(**kwargs):
     22
     23    def _cache_controller(viewfunc):
     24
     25        def _cache_controlled(request, *args, **kw):
     26            response = viewfunc(request, *args, **kw)
     27            patch_cache_control(response, **kwargs)
     28            return response
     29
     30        return _cache_controlled
     31
     32    return _cache_controller
     33
  • docs/cache.txt

     
    270270
    271271.. _`HTTP Vary headers`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44
    272272
     273Controlling cache: Using Vary headers
     274=====================================
     275
     276Another problem with caching is the privacy of data, and the question where data can
     277be stored in a cascade of caches. A user usually faces two kinds of caches: his own
     278browser cache (a private cache) and his providers cache (a public cache). A public cache
     279is used by multiple users and controlled by someone else. This poses problems with private
     280(in the sense of sensitive) data - you don't want your social security number or your
     281banking account numbers stored in some public cache. So web applications need a way
     282to tell the caches what data is private and what is public.
     283
     284Other aspects are the definition how long a page should be cached at max, or wether the
     285cache should allways check for newer versions and only deliver the cache content when
     286there were no changes (some caches might deliver cached content even if the server page
     287changed - just because the cache copy isn't yet expired).
     288
     289So there are a multitude of options you can control for your pages. This is where the
     290Cache-Control header (more infos in `HTTP Cache-Control headers`_) comes in. The usage
     291is quite simple::
     292
     293    @cache_control(private=True, must_revalidate=True, max_age=3600)
     294    def my_view(request):
     295        ...
     296
     297This would define the view as private, to be revalidated on every access and cache
     298copies will only be stored for 3600 seconds at max.
     299
     300The caching middleware already set's this header up with a max-age of the CACHE_MIDDLEWARE_SETTINGS
     301setting. And the cache_page decorator does the same. The cache_control decorator correctly merges
     302different values into one big header, though. But you should take into account that middlewares
     303might overwrite some of your headers or set their own defaults if you don't give that header yourself.
     304
     305.. _`HTTP Cache-Control headers`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
     306
    273307Other optimizations
    274308===================
    275309
Back to Top