web-dev-qa-db-ja.com

Djangoでのクライアント側のキャッシュとの戦い

Render_to_responseショートカットを使用していますが、特定のResponseオブジェクトを作成して、ヘッダーを追加してクライアント側のキャッシュを防止したくありません。

次の内容を含む応答が必要です。

  • プラグマ:no-cache
  • キャッシュ制御:キャッシュなし
  • キャッシュ制御:再検証が必要

そして、ブラウザがキャッシュを回避するためのディレクティブとして解釈する他のすべての気の利いた方法。

キャッシュなしのミドルウェアや、コードの侵入を最小限に抑えながらトリックを実行できる類似のものはありますか?

66
Lorenzo

Cache_controlデコレータを使用してこれを実現できます。 ドキュメント の例:

from Django.views.decorators.cache import never_cache

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

カスタムミドルウェアを使用したこのアプローチ(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


これをUpdateCacheMiddlewareおよびFetchFromCacheMiddlewareと組み合わせて、クライアント側のキャッシュを無効にしながらサーバー側のキャッシュを有効にするには、このように他のすべての前にDisableClientSideCachingMiddlewareを追加する必要があります:

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

既存の回答を補足するため。キャッシングを無効にするためにヘッダーを追加するデコレーターは次のとおりです。

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')
14
Jan Wrobel

実際、自分のミドルウェアを書くのは簡単でした。

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デコレータも動作しません

7
Lorenzo

Google Chrome browser(Version 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
Erwan

@ Meil​​o's answer for 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
2
Zags

FirefoxとSafariで3つの魔法metaが機能しなかったとき、頭を掻きました。

<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',
    ...
2
Hussain