Fighting client-side caching in Django
To supplement existing answers. Here is a decorator that adds additional headers to disable caching:
from django.views.decorators.cache import patch_cache_control
from functools import wraps
def never_ever_cache(decorated_function):
"""Like Django @never_cache but sets more valid cache disabling headers.
@never_cache only sets Cache-Control:max-age=0 which is not
enough. For example, with max-axe=0 Firefox returns cached results
of GET calls when it is restarted.
"""
@wraps(decorated_function)
def wrapper(*args, **kwargs):
response = decorated_function(*args, **kwargs)
patch_cache_control(
response, no_cache=True, no_store=True, must_revalidate=True,
max_age=0)
return response
return wrapper
And you can use it like:
class SomeView(View):
@method_decorator(never_ever_cache)
def get(self, request):
return HttpResponse('Hello')
You can achieve this using the cache_control decorator. Example from the documentation:
from django.views.decorators.cache import never_cache
@never_cache
def myview(request):
# ...
This approach (slight modification of L. De Leo's solution) with a custom middleware has worked well for me as a site wide solution:
from django.utils.cache import add_never_cache_headers
class DisableClientSideCachingMiddleware(object):
def process_response(self, request, response):
add_never_cache_headers(response)
return response
This makes use of add_never_cache_headers
.
If you want to combine this with UpdateCacheMiddleware
and FetchFromCacheMiddleware
, to enable server-side caching while disabling client-side caching, you need to add DisableClientSideCachingMiddleware
before everything else, like this:
MIDDLEWARE_CLASSES = (
'custom.middleware.DisableClientSideCachingMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
# ... all other middleware ...
'django.middleware.cache.FetchFromCacheMiddleware',
)