Browse Source

Fixed #13008 -- Added more Cache-Control headers to never_cache() decorator.

Markus Bertheau 10 years ago
parent
commit
4a438e400b

+ 1 - 0
django/utils/cache.py

@@ -134,6 +134,7 @@ def add_never_cache_headers(response):
     Adds headers to a response to indicate that a page should never be cached.
     """
     patch_response_headers(response, cache_timeout=-1)
+    patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True)
 
 
 def patch_vary_headers(response, newheaders):

+ 1 - 1
docs/ref/contrib/admin/index.txt

@@ -1474,7 +1474,7 @@ templates used by the :class:`ModelAdmin` views:
         url(r'^my_view/$', self.admin_site.admin_view(self.my_view))
 
     This wrapping will protect ``self.my_view`` from unauthorized access and
-    will apply the ``django.views.decorators.cache.never_cache`` decorator to
+    will apply the :func:`django.views.decorators.cache.never_cache` decorator to
     make sure it is not cached if the cache middleware is active.
 
     If the page is cacheable, but you still want the permission check to be

+ 7 - 1
docs/ref/utils.txt

@@ -65,7 +65,13 @@ need to distinguish caches by the ``Accept-language`` header.
 
 .. function:: add_never_cache_headers(response)
 
-    Adds headers to a response to indicate that a page should never be cached.
+    Adds a ``Cache-Control: max-age=0, no-cache, no-store, must-revalidate``
+    header to a response to indicate that a page should never be cached.
+
+    .. versionchanged:: 1.9
+
+        Before Django 1.9, ``Cache-Control: max-age=0`` was sent. This didn't
+        reliably prevent caching in all browsers.
 
 .. function:: patch_vary_headers(response, newheaders)
 

+ 4 - 0
docs/releases/1.9.txt

@@ -118,6 +118,10 @@ Cache
 * ``django.core.cache.backends.base.BaseCache`` now has a ``get_or_set()``
   method.
 
+* :func:`django.views.decorators.cache.never_cache` now sends more persuasive
+  headers (added ``no-cache, no-store, must-revalidate`` to ``Cache-Control``)
+  to better prevent caching.
+
 Email
 ^^^^^
 

+ 1 - 1
docs/topics/cache.txt

@@ -1209,7 +1209,7 @@ the value of the :setting:`CACHE_MIDDLEWARE_SECONDS` setting. If you use a custo
 precedence, and the header values will be merged correctly.)
 
 If you want to use headers to disable caching altogether,
-``django.views.decorators.cache.never_cache`` is a view decorator that adds
+:func:`django.views.decorators.cache.never_cache` is a view decorator that adds
 headers to ensure the response won't be cached by browsers or other caches.
 Example::
 

+ 19 - 0
docs/topics/http/decorators.txt

@@ -97,3 +97,22 @@ caching based on specific request headers.
     into account when building its cache key.
 
     See :ref:`using vary headers <using-vary-headers>`.
+
+.. module:: django.views.decorators.cache
+
+Caching
+=======
+
+The decorators in :mod:`django.views.decorators.cache` control server and
+client-side caching.
+
+.. function:: never_cache(view_func)
+
+    This decorator adds a ``Cache-Control: max-age=0, no-cache, no-store,
+    must-revalidate`` header to a response to indicate that a page should never
+    be cached.
+
+    .. versionchanged:: 1.9
+
+        Before Django 1.9, ``Cache-Control: max-age=0`` was sent. This didn't
+        reliably prevent caching in all browsers.

+ 12 - 0
tests/decorators/tests.py

@@ -317,3 +317,15 @@ class XFrameOptionsDecoratorsTests(TestCase):
         # the middleware's functionality, let's make sure it actually works...
         r = XFrameOptionsMiddleware().process_response(req, resp)
         self.assertEqual(r.get('X-Frame-Options', None), None)
+
+
+class NeverCacheDecoratorTest(TestCase):
+    def test_never_cache_decorator(self):
+        @never_cache
+        def a_view(request):
+            return HttpResponse()
+        r = a_view(HttpRequest())
+        self.assertEqual(
+            set(r['Cache-Control'].split(', ')),
+            {'max-age=0', 'no-cache', 'no-store', 'must-revalidate'},
+        )