在 Django 中打击客户端缓存

我正在使用 render _ to _ Response 快捷方式,不想精心制作一个特定的 Response 对象来添加额外的头文件,以防止客户端缓存。

我想有一个答复,其中包括:

  • Pragma: no-cache
  • 缓存控制: 无缓存
  • 缓存控制: 必须重新验证

以及所有其他浏览器希望解释为指令以避免缓存的漂亮方式。

有没有一个无缓存的中间件或类似的东西,可以做到这一点,以最小的代码入侵?

39472 次浏览

您可以使用 cache _ control 装饰器来实现这一点:

from django.views.decorators.cache import never_cache


@never_cache
def myview(request):
# ...

实际上,编写自己的中间件非常容易:

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

仍然没有真正表现出我想要的样子,但是@never _ cache 装饰器也是如此

这种方法(稍微修改了 L. De Leo 的解决方案)和一个定制的中间件,作为站点范围的解决方案,对我来说非常有效:

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

这就利用了 add_never_cache_headers


如果您想将其与 UpdateCacheMiddlewareFetchFromCacheMiddleware结合起来,以便在禁用客户端缓存的同时启用服务器端缓存,那么您需要在所有其他内容之前添加 DisableClientSideCachingMiddleware,如下所示:

MIDDLEWARE_CLASSES = (
'custom.middleware.DisableClientSideCachingMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
# ... all other middleware ...
'django.middleware.cache.FetchFromCacheMiddleware',
)

为了补充现有的答案,这里有一个装饰器,它添加了额外的标题来禁用缓存:

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

你可以这样使用:

class SomeView(View):
@method_decorator(never_ever_cache)
def get(self, request):
return HttpResponse('Hello')

关于 Google Chrome 浏览器(版本34.0.1847.116 m)和其他浏览器,我发现只有 @cache_control装饰器可以工作。我使用 Django 1.6.2。

像这样使用它:

@cache_control(max_age=0, no_cache=True, no_store=True, must_revalidate=True)
def view(request):
...

下面是为 Django 1.10 + 改写的 @ Meilo 的回答:

from django.utils.cache import add_never_cache_headers


class DisableClientCachingMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response


def __call__(self, request):
response = self.get_response(request)
add_never_cache_headers(response)
return response

当三个神奇的 meta不能在 Firefox 和 Safari 中工作时,我挠了挠头。

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

显然,这是可能发生的,因为一些浏览器会忽略客户端 meta,所以应该在服务器端处理它。

我尝试了所有的答案从这个职位为我的班级为基础的意见(django==1.11.6)。但是参照“ Lorenzo”和“ Zags”的答案,我决定写一个我认为很简单的中间件。

So adding to other good answers,

# middleware.py
class DisableBrowserCacheMiddleware(object):


def __init__(self, get_response):
self.get_response = get_response


def __call__(self, request):
response = self.get_response(request)
response['Pragma'] = 'no-cache'
response['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response['Expires'] = '0'
return response


# settings.py
MIDDLEWARE = [
'myapp.middleware.DisableBrowserCacheMiddleware',
...