我正在使用render_to_response快捷方式,并且不想制作特定的Response对象来添加其他标头,以防止客户端缓存。
我想要一个包含以下内容的回复:
- 语法:无缓存
- 缓存控制:无缓存
- 缓存控制:必须重新验证
浏览器希望将所有其他巧妙的方式解释为指令以避免缓存。
是否有没有缓存的中间件或类似的东西可以以最少的代码入侵来解决问题?
Answers:
您可以使用cache_control装饰器实现此目的。文档中的示例:
from django.views.decorators.cache import never_cache
@never_cache
def myview(request):
# ...
patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True)
response['Pragma'] = 'no-cache'
@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
如果要将其与UpdateCacheMiddleware
和结合使用FetchFromCacheMiddleware
,以在禁用客户端缓存的同时启用服务器端缓存,则需要先添加DisableClientSideCachingMiddleware
其他内容,如下所示:
MIDDLEWARE_CLASSES = (
'custom.middleware.DisableClientSideCachingMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
# ... all other middleware ...
'django.middleware.cache.FetchFromCacheMiddleware',
)
add_never_cache_headers
而不是手动插入标头。
add_never_cache_headers
还将Expires和Last-Modified标头设置为当前时间。如果在您的设置中设置了USE_ETAGS,它还将设置ETag标头避免缓存。见github.com/django/django/blob/master/django/utils/cache.py
补充现有答案。这是一个装饰器,它添加了其他标头以禁用缓存:
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')
实际上,编写自己的中间件很容易:
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装饰器也没有
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的答案,我决定编写一种我认为很简单的中间件。
因此,除了其他好的答案之外,
# 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',
...
response["Cache-Control"] = "no-cache, no-store, must-revalidate"
和一起添加@never_cache
。@never_cache
调用add_never_cache_headers()
,然后依次调用,patch_cache_control()
但这只会添加Cache-Control:max-age=0
,显然对于这些浏览器来说还不够。见 stackoverflow.com/questions/49547/...