2010-01-19 12 views
60

Estoy usando el acceso directo render_to_response y no quiero crear un objeto Response específico para agregar encabezados adicionales para evitar el almacenamiento en caché del lado del cliente.Combatir el almacenamiento en caché del lado del cliente en Django

Me gustaría tener una respuesta que contiene:

  • Pragma: no-cache
  • Cache-Control: no-cache
  • Cache-Control: hay que revalidar

Y todas las otras formas ingeniosas que los navegadores interpretarán como directivas para evitar el almacenamiento en caché.

¿Hay algún middleware sin caché o algo similar que pueda solucionar el problema con una mínima intrusión de código?

Respuesta

79

Puede lograr esto utilizando el decorador cache_control. Ejemplo de la documentation:

from django.views.decorators.cache import never_cache 

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

Para que esto funcione en todos los navegadores (en concreto Firefox y Opera, que funcionaba bien en IE y Safari/Chrome) que necesitaba para añadir manualmente 'respuesta [" Caché -Control "] =" no-cache, no-store, must-revalidate "' junto con '@ never_cache'. '@ never_cache' llama a' add_never_cache_headers() 'y esto a su vez llama a' patch_cache_control() 'pero esto solo agrega' Cache-Control: max-age = 0', que aparentemente no es suficiente para estos navegadores. Ver http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers – AJJ

+7

Después de explorar el código django un poco más, encontré una forma más clara de agregar ese encabezado: 'patch_cache_control (response, no_cache = True, no_store = True, must_revalidate = True)' – AJJ

+6

Ah, ya hay un ticket abierto para esto en code.djangoproject.com: [@never_cache decorator debería agregar 'no-cache '&' debe-revalidar '] (https://code.djangoproject.com/ticket/13008) – AJJ

7

escribir mi propia realidad middleware era bastante fácil:

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 

Aún en realidad no se comportan como yo quería, pero por lo que tampoco lo hace el decorador @never_cache

+1

Esta respuesta a * Asegurarse de que una página web no esté en caché, en todos los navegadores * es bastante detallada: http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached- across-all-browsers – AJJ

42

Este enfoque (una ligera modificación de la solución de L. De Leo) con un middleware personalizado me ha funcionado como una solución para todo el sitio:

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 

Esto hace uso de add_never_cache_headers.


Si desea combinar esto con UpdateCacheMiddleware y FetchFromCacheMiddleware, para permitir el almacenamiento en caché del lado del servidor, mientras que deshabilitar la caché del cliente, es necesario agregar DisableClientSideCachingMiddleware antes que nada, de esta manera:

MIDDLEWARE_CLASSES = (
    'custom.middleware.DisableClientSideCachingMiddleware', 
    'django.middleware.cache.UpdateCacheMiddleware', 
    # ... all other middleware ... 
    'django.middleware.cache.FetchFromCacheMiddleware', 
) 
+5

+1 para usar 'add_never_cache_headers' en lugar de insertar encabezados manualmente. –

+0

He empacado algo basado en esto. Ahora está disponible en PyPI y github. https://github.com/incuna/django-never-cache-post – meshy

+0

Sólo un fyi: Esto realmente no funciona para Opera y el almacenamiento en caché de páginas, porque add_never_cache simplemente establece max-age a cero, y O, y Opera no parece respetar la edad máxima para ese propósito. Consulte http://my.opera.com/yngve/blog/2007/02/27/introducing-cache-contexts-or-why-the – AdamC

13

Para complementar las respuestas existentes. Aquí es un decorador que añade cabeceras adicionales para deshabilitar el caché:

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 

Y se puede utilizar como:

class SomeView(View): 
    @method_decorator(never_ever_cache) 
    def get(self, request): 
     return HttpResponse('Hello') 
+0

¿Puede alguien explicar el voto negativo? Me pregunto si algo está fundamentalmente mal con el código, porque dependo de él en un sistema de producción. –

+0

+1 Funciona bien para mí también y no veo ningún problema tampoco. Escuchar una razón del infractor sería realmente apreciado. – zerm

5

En cuanto al navegador Google Chrome (versión 34.0.1847.116 m) y los otros navegadores, Descubrí que solo el decorador @cache_control está funcionando. Yo uso Django 1.6.2.

utilizar de esta manera:

@cache_control(max_age=0, no_cache=True, no_store=True, must_revalidate=True) 
def view(request): 
    ... 
+0

¿Cuál es la mejor manera de hacer esto cuando uno usa vistas basadas en clases? –

2

Aquí es una reescritura de @Meilo's answer de 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 
0

me estaba rascando la cabeza cuando los tres magia meta no funcionó en Firefox y 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" /> 

Aparentemente puede suceder debido a que algunos navegadores ignorar el lado del cliente meta, por lo que debe ser manejado en el lado del servidor.

He intentado todas las respuestas de esta publicación para mis vistas basadas en clase (django==1.11.6). Pero refiriéndome a las respuestas de @Lorenzo y @Zags, decidí escribir un middleware que creo que es simple.

por lo que añadir a otras buenas respuestas,

# 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', 
    ... 
Cuestiones relacionadas