app/django/middleware/cache.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 from django.conf import settings
       
     2 from django.core.cache import cache
       
     3 from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age
       
     4 
       
     5 class CacheMiddleware(object):
       
     6     """
       
     7     Cache middleware. If this is enabled, each Django-powered page will be
       
     8     cached (based on URLs).
       
     9 
       
    10     Only parameter-less GET or HEAD-requests with status code 200 are cached.
       
    11 
       
    12     The number of seconds each page is stored for is set by the
       
    13     "max-age" section of the response's "Cache-Control" header, falling back to
       
    14     the CACHE_MIDDLEWARE_SECONDS setting if the section was not found.
       
    15 
       
    16     If CACHE_MIDDLEWARE_ANONYMOUS_ONLY is set to True, only anonymous requests
       
    17     (i.e., those not made by a logged-in user) will be cached. This is a
       
    18     simple and effective way of avoiding the caching of the Django admin (and
       
    19     any other user-specific content).
       
    20 
       
    21     This middleware expects that a HEAD request is answered with a response
       
    22     exactly like the corresponding GET request.
       
    23 
       
    24     When a hit occurs, a shallow copy of the original response object is
       
    25     returned from process_request.
       
    26 
       
    27     Pages will be cached based on the contents of the request headers
       
    28     listed in the response's "Vary" header. This means that pages shouldn't
       
    29     change their "Vary" header.
       
    30 
       
    31     This middleware also sets ETag, Last-Modified, Expires and Cache-Control
       
    32     headers on the response object.
       
    33     """
       
    34     def __init__(self, cache_timeout=None, key_prefix=None, cache_anonymous_only=None):
       
    35         self.cache_timeout = cache_timeout
       
    36         if cache_timeout is None:
       
    37             self.cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
       
    38         self.key_prefix = key_prefix
       
    39         if key_prefix is None:
       
    40             self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
       
    41         if cache_anonymous_only is None:
       
    42             self.cache_anonymous_only = getattr(settings, 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY', False)
       
    43         else:
       
    44             self.cache_anonymous_only = cache_anonymous_only
       
    45 
       
    46     def process_request(self, request):
       
    47         "Checks whether the page is already cached and returns the cached version if available."
       
    48         if self.cache_anonymous_only:
       
    49             assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware."
       
    50 
       
    51         if not request.method in ('GET', 'HEAD') or request.GET:
       
    52             request._cache_update_cache = False
       
    53             return None # Don't bother checking the cache.
       
    54 
       
    55         if self.cache_anonymous_only and request.user.is_authenticated():
       
    56             request._cache_update_cache = False
       
    57             return None # Don't cache requests from authenticated users.
       
    58 
       
    59         cache_key = get_cache_key(request, self.key_prefix)
       
    60         if cache_key is None:
       
    61             request._cache_update_cache = True
       
    62             return None # No cache information available, need to rebuild.
       
    63 
       
    64         response = cache.get(cache_key, None)
       
    65         if response is None:
       
    66             request._cache_update_cache = True
       
    67             return None # No cache information available, need to rebuild.
       
    68 
       
    69         request._cache_update_cache = False
       
    70         return response
       
    71 
       
    72     def process_response(self, request, response):
       
    73         "Sets the cache, if needed."
       
    74         if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache:
       
    75             # We don't need to update the cache, just return.
       
    76             return response
       
    77         if request.method != 'GET':
       
    78             # This is a stronger requirement than above. It is needed
       
    79             # because of interactions between this middleware and the
       
    80             # HTTPMiddleware, which throws the body of a HEAD-request
       
    81             # away before this middleware gets a chance to cache it.
       
    82             return response
       
    83         if not response.status_code == 200:
       
    84             return response
       
    85         # Try to get the timeout from the "max-age" section of the "Cache-
       
    86         # Control" header before reverting to using the default cache_timeout
       
    87         # length.
       
    88         timeout = get_max_age(response)
       
    89         if timeout == None:
       
    90             timeout = self.cache_timeout
       
    91         elif timeout == 0:
       
    92             # max-age was set to 0, don't bother caching.
       
    93             return response
       
    94         patch_response_headers(response, timeout)
       
    95         cache_key = learn_cache_key(request, response, timeout, self.key_prefix)
       
    96         cache.set(cache_key, response, timeout)
       
    97         return response