Борьба с кэшированием на стороне клиента в Django - PullRequest
66 голосов
/ 19 января 2010

Я использую ярлык render_to_response и не хочу создавать конкретный объект Response для добавления дополнительных заголовков для предотвращения кэширования на стороне клиента.

Я хотел бы получить ответ, содержащий:

  • Прагма: без кэша
  • Контроль кэша: без кэширования
  • Cache-control: must-revalidate

И все другие изящные способы, которые браузеры, вероятно, будут интерпретировать как директивы, чтобы избежать кеширования.

Существует ли промежуточное программное обеспечение без кэша или что-то подобное, способное добиться цели с минимальным вмешательством кода?

Ответы [ 7 ]

89 голосов
/ 19 января 2010

Этого можно добиться с помощью декоратора cache_control. Пример из документации :

from django.views.decorators.cache import never_cache

@never_cache
def myview(request):
   # ...
45 голосов
/ 04 мая 2011

Этот подход (небольшая модификация решения Л. Де Лео) с пользовательским промежуточным программным обеспечением хорошо работал для меня как решения для всего сайта:

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',
)
14 голосов
/ 22 ноября 2012

Дополнить существующие ответы.Вот декоратор, который добавляет дополнительные заголовки для отключения кэширования:

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')
7 голосов
/ 20 января 2010

На самом деле написать собственное промежуточное программное обеспечение было достаточно просто:

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 не делает

5 голосов
/ 14 апреля 2014

Что касается браузера 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):
    ...
2 голосов
/ 06 февраля 2018

Я чесал голову, когда три волшебства 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',
    ...
2 голосов
/ 07 декабря 2017

Вот переписывание @ ответа Мейло для Джанго 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...