Django キャッシュの落とし穴: never_cache() デコレータと add_never_cache_headers() 関数の活用


Django の django.views.decorators.cache.cache_control() デコレータは、ビュー関数の応答に Cache-Control ヘッダーを追加することで、クライアントサイドとサーバーサイドのキャッシュを制御します。このヘッダーは、ブラウザやキャッシュサーバーがコンテンツをどのくらい長くキャッシュするべきかを指示します。

使用方法

cache_control() デコレータは、ビュー関数の装飾に使用されます。デコレータの引数として、Cache-Control ヘッダーに設定するオプションを指定できます。

オプション

  • must-revalidate: キャッシュされたコンテンツが有効期限切れになる前に、サーバーに検証を求めることを示します。
  • no-store: コンテンツがブラウザのキャッシュに保存されないことを示します。
  • no-cache: コンテンツがキャッシュされないことを示します。
  • public: コンテンツがパブリックキャッシュでキャッシュされることを示します。
  • private: コンテンツがプライベートキャッシュのみでキャッシュされることを示します。
  • max_age: コンテンツがキャッシュされる最大時間 (秒) を指定します。

from django.views.decorators.cache import cache_control

@cache_control(max_age=3600)
def my_view(request):
    # ...
    return HttpResponse('Hello, world!')

この例では、my_view() 関数の応答には Cache-Control: max-age=3600 ヘッダーが追加されます。これは、ブラウザやキャッシュサーバーがコンテンツを最大 1 時間 (3600 秒) キャッシュすることを意味します。

詳細

cache_control() デコレータは、django.middleware.cache.CacheMiddleware ミドルウェアと連携して動作します。このミドルウェアは、すべてのビュー関数の応答に Cache-Control ヘッダーを追加します。cache_control() デコレータは、このミドルウェアの設定をオーバーライドするために使用できます。

利点

cache_control() デコレータを使用すると、以下の利点があります。

  • ユーザーエクスペリエンスの向上: キャッシュにより、ユーザーはより早くコンテンツにアクセスできます。
  • 帯域幅の節約: キャッシュされたコンテンツを配信することで、ネットワーク帯域幅を節約できます。
  • パフォーマンスの向上: 頻繁にアクセスされるコンテンツをキャッシュすることで、サーバーの負荷を軽減し、ページの読み込み時間を短縮できます。

注意点

cache_control() デコレータを使用する際には、以下の点に注意する必要があります。

  • キャッシュ無効化: キャッシュされたコンテンツを無効化するには、CacheMiddleware ミドルウェアの cache_vary_headers 設定を使用する必要があります。
  • ユーザー認証: 認証が必要なコンテンツには、キャッシュを使用しないようにする必要があります。
  • コンテンツの更新: コンテンツが頻繁に変更される場合は、キャッシュ時間が短すぎるように設定する必要があります。


from django.views.decorators.cache import cache_control

@cache_control(max_age=3600)
def my_view(request):
    # ...
    return HttpResponse('Hello, world!')

この例では、my_view() 関数の応答は最大 1 時間 (3600 秒) キャッシュされます。

例 2: コンテンツをプライベートキャッシュのみでキャッシュする

from django.views.decorators.cache import cache_control

@cache_control(private=True)
def my_view(request):
    # ...
    return HttpResponse('Hello, world!')

この例では、my_view() 関数の応答はプライベートキャッシュのみでキャッシュされます。これは、ブラウザのキャッシュには保存されず、ユーザーがブラウザを閉じると失われることを意味します。

例 3: コンテンツをキャッシュしない

from django.views.decorators.cache import cache_control

@cache_control(no_cache=True)
def my_view(request):
    # ...
    return HttpResponse('Hello, world!')

この例では、my_view() 関数の応答はキャッシュされません。これは、ブラウザやキャッシュサーバーがコンテンツを保存しないことを意味します。

例 4: 複数のオプションを組み合わせる

from django.views.decorators.cache import cache_control

@cache_control(max_age=3600, private=True, must_revalidate=True)
def my_view(request):
    # ...
    return HttpResponse('Hello, world!')

この例では、my_view() 関数の応答は最大 1 時間 (3600 秒) プライベートキャッシュに保存され、キャッシュされたコンテンツが有効期限切れになる前にサーバーに検証を求めます。



cache_page() デコレータ

cache_page() デコレータは、ビュー関数の応答をキャッシュする最も一般的な方法です。このデコレータは、URL とリクエストヘッダーに基づいてキャッシュキーを生成します。また、CacheMiddleware ミドルウェアと連携して、キャッシュヘッダーを応答に追加します。

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request):
    # ...
    return HttpResponse('Hello, world!')

この例では、my_view() 関数の応答は最大 15 分 (60 * 15 秒) キャッシュされます。

never_cache() デコレータ

never_cache() デコレータは、ビュー関数の応答をキャッシュしないことを示すために使用されます。

from django.views.decorators.cache import never_cache

@never_cache
def my_view(request):
    # ...
    return HttpResponse('Hello, world!')

この例では、my_view() 関数の応答はキャッシュされません。

add_never_cache_headers() 関数

add_never_cache_headers() 関数は、ビュー関数の応答に Cache-Control: no-cache, no-store, must-revalidate, private ヘッダーを追加するために使用されます。

from django.utils.cache import add_never_cache_headers

def my_view(request):
    response = HttpResponse('Hello, world!')
    add_never_cache_headers(response)
    return response

キャッシュミドルウェアの設定

CacheMiddleware ミドルウェアの設定を変更することで、ビュー関数のキャッシュを制御することもできます。

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
        'TIMEOUT': 60,
    },
}

この例では、すべてのビュー関数の応答は最大 1 分 (60 秒) キャッシュされます。