/django/views/decorators/cache.py
https://github.com/nrb/django · Python · 92 lines · 86 code · 4 blank · 2 comment · 2 complexity · 6834c9f3062cab97a7ebe1104f133957 MD5 · raw file
- from functools import wraps
- from django.utils.decorators import decorator_from_middleware_with_args, available_attrs
- from django.utils.cache import patch_cache_control, add_never_cache_headers
- from django.middleware.cache import CacheMiddleware
- def cache_page(*args, **kwargs):
- """
- Decorator for views that tries getting the page from the cache and
- populates the cache if the page isn't in the cache yet.
- The cache is keyed by the URL and some data from the headers.
- Additionally there is the key prefix that is used to distinguish different
- cache areas in a multi-site setup. You could use the
- sites.get_current().domain, for example, as that is unique across a Django
- project.
- Additionally, all headers from the response's Vary header will be taken
- into account on caching -- just like the middleware does.
- """
- # We need backwards compatibility with code which spells it this way:
- # def my_view(): pass
- # my_view = cache_page(my_view, 123)
- # and this way:
- # my_view = cache_page(123)(my_view)
- # and this:
- # my_view = cache_page(my_view, 123, key_prefix="foo")
- # and this:
- # my_view = cache_page(123, key_prefix="foo")(my_view)
- # and possibly this way (?):
- # my_view = cache_page(123, my_view)
- # and also this way:
- # my_view = cache_page(my_view)
- # and also this way:
- # my_view = cache_page()(my_view)
- # We also add some asserts to give better error messages in case people are
- # using other ways to call cache_page that no longer work.
- cache_alias = kwargs.pop('cache', None)
- key_prefix = kwargs.pop('key_prefix', None)
- assert not kwargs, "The only keyword arguments are cache and key_prefix"
- def warn():
- import warnings
- warnings.warn('The cache_page decorator must be called like: '
- 'cache_page(timeout, [cache=cache name], [key_prefix=key prefix]). '
- 'All other ways are deprecated.',
- PendingDeprecationWarning,
- stacklevel=3)
- if len(args) > 1:
- assert len(args) == 2, "cache_page accepts at most 2 arguments"
- warn()
- if callable(args[0]):
- return decorator_from_middleware_with_args(CacheMiddleware)(cache_timeout=args[1], cache_alias=cache_alias, key_prefix=key_prefix)(args[0])
- elif callable(args[1]):
- return decorator_from_middleware_with_args(CacheMiddleware)(cache_timeout=args[0], cache_alias=cache_alias, key_prefix=key_prefix)(args[1])
- else:
- assert False, "cache_page must be passed a view function if called with two arguments"
- elif len(args) == 1:
- if callable(args[0]):
- warn()
- return decorator_from_middleware_with_args(CacheMiddleware)(cache_alias=cache_alias, key_prefix=key_prefix)(args[0])
- else:
- # The One True Way
- return decorator_from_middleware_with_args(CacheMiddleware)(cache_timeout=args[0], cache_alias=cache_alias, key_prefix=key_prefix)
- else:
- warn()
- return decorator_from_middleware_with_args(CacheMiddleware)(cache_alias=cache_alias, key_prefix=key_prefix)
- def cache_control(**kwargs):
- def _cache_controller(viewfunc):
- @wraps(viewfunc, assigned=available_attrs(viewfunc))
- def _cache_controlled(request, *args, **kw):
- response = viewfunc(request, *args, **kw)
- patch_cache_control(response, **kwargs)
- return response
- return _cache_controlled
- return _cache_controller
- def never_cache(view_func):
- """
- Decorator that adds headers to a response so that it will
- never be cached.
- """
- @wraps(view_func, assigned=available_attrs(view_func))
- def _wrapped_view_func(request, *args, **kwargs):
- response = view_func(request, *args, **kwargs)
- add_never_cache_headers(response)
- return response
- return _wrapped_view_func