Fighting client-side caching in Django
I'm using the render_to_response shortcut and don't want to craft a specific Response object to add additional headers to prevent client-side caching.
I'd like to have a response that contains:
- Pragma: no-cache
- Cache-control : no-cache
- Cache-control: must-revalidate
And all the other nifty ways that browsers will hopefully interpret as directives to avoid caching.
Is there a no-cache middleware or something similar that can do the trick with minimal code intrusion?
Solution 1:
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):
# ...
Solution 2:
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',
)
Solution 3:
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')
Solution 4:
Actually writing my own middleware was easy enough:
from django.http import HttpResponse
class NoCacheMiddleware(object):
def process_response(self, request, response):
response['Pragma'] = 'no-cache'
response['Cache-Control'] = 'no-cache must-revalidate proxy-revalidate'
return response
Still doesn't really behave like i wanted but so neither does the @never_cache decorator