在Django中战斗客户端缓存

时间:2010-01-19 17:29:52

标签: django caching

我正在使用render_to_response快捷方式,并且不希望创建特定的Response对象来添加其他标头以防止客户端缓存。

我想要一个包含以下内容的回复:

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

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

是否有一个无缓存的中间件或类似的东西可以用最少的代码入侵来实现这个技巧?

7 个答案:

答案 0 :(得分:88)

您可以使用cache_control装饰器实现此目的。 documentation的示例:

from django.views.decorators.cache import never_cache

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

答案 1 :(得分:45)

使用自定义中间件的这种方法(略微修改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',
)

答案 2 :(得分:14)

补充现有答案。这是一个装饰器,添加额外的标头来禁用缓存:

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')

答案 3 :(得分:7)

实际上编写我自己的中间件很容易:

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装饰者

也没有

答案 4 :(得分:5)

关于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):
    ...

答案 5 :(得分:2)

这是Django 1.10 +的重写@Meilo's answer

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

答案 6 :(得分:2)

当三个魔法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',
    ...