在Django中战斗客户端缓存

Lor*_*nzo 66 django caching

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

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

  • Pragma:没有缓存
  • 缓存控制:无缓存
  • 缓存控制:必须重新验证

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

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

Kri*_*ian 89

您可以使用cache_control装饰器实现此目的.文档中的示例:

from django.views.decorators.cache import never_cache

@never_cache
def myview(request):
   # ...
Run Code Online (Sandbox Code Playgroud)

  • 为了使这个适用于所有浏览器(特别是FireFox和Opera,它在IE和Safari/Chrome上运行良好)我需要手动添加`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`,这对于这些浏览器来说显然是不够的.请参阅http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers (15认同)
  • 在探索了django代码之后,我发现了一种更简洁的添加标题的方法:`patch_cache_control(response,no_cache = True,no_store = True,must_revalidate = True) (9认同)
  • 啊,在code.djangoproject.com上已经有一张打开的票了:[@never_cache装饰器应该添加'no-cache'和'must-revalidate'](https://code.djangoproject.com/ticket/13008) (6认同)
  • 2018年更新:```@ never_cache```已修复,适用于所有浏览器. (3认同)
  • @AJJ 我想你也错过了 `response['Pragma'] = 'no-cache'` (2认同)

Mei*_*ilo 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
Run Code Online (Sandbox Code Playgroud)

这利用了add_never_cache_headers.


如果要将其与UpdateCacheMiddlewareFetchFromCacheMiddleware,以及在禁用客户端缓存时启用服务器端缓存,则需要DisableClientSideCachingMiddleware在其他所有内容之前添加,如下所示:

MIDDLEWARE_CLASSES = (
    'custom.middleware.DisableClientSideCachingMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware',
    # ... all other middleware ...
    'django.middleware.cache.FetchFromCacheMiddleware',
)
Run Code Online (Sandbox Code Playgroud)

  • +1使用`add_never_cache_headers`而不是手动插入标题. (5认同)

Jan*_*bel 15

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

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
Run Code Online (Sandbox Code Playgroud)

你可以使用它:

class SomeView(View):
    @method_decorator(never_ever_cache)
    def get(self, request):
        return HttpResponse('Hello')
Run Code Online (Sandbox Code Playgroud)


Lor*_*nzo 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
Run Code Online (Sandbox Code Playgroud)

仍然没有像我想要的那样,但是@never_cache装饰器也没有


Hus*_*ain 6

当这三个魔法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" />
Run Code Online (Sandbox Code Playgroud)

显然它会发生,因为一些浏览器会忽略客户端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',
    ...
Run Code Online (Sandbox Code Playgroud)


Erw*_*wan 5

关于谷歌Chrome浏览器(版本34.0.1847.116米)和其他浏览器,我发现只有@cache_control装饰器正在工作.我使用Django 1.6.2.

像这样使用它:

@cache_control(max_age=0, no_cache=True, no_store=True, must_revalidate=True)
def view(request):
    ...
Run Code Online (Sandbox Code Playgroud)


Zag*_*ags 5

这是@Meilo对 Django 1.10+的回答的重写:

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
Run Code Online (Sandbox Code Playgroud)