Ticket #13283: 13283_github_pull_4.diff
File 13283_github_pull_4.diff, 9.1 KB (added by , 14 years ago) |
---|
-
django/middleware/cache.py
diff --git a/django/middleware/cache.py b/django/middleware/cache.py index a3076ac..68345cc 100644
a b More details about how the caching works: 50 50 51 51 from django.conf import settings 52 52 from django.core.cache import cache 53 from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age 53 from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age, has_vary_header 54 54 55 55 class UpdateCacheMiddleware(object): 56 56 """ … … class UpdateCacheMiddleware(object): 66 66 self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX 67 67 self.cache_anonymous_only = getattr(settings, 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY', False) 68 68 69 def _should_update_cache(self, request, response): 70 if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache: 71 return False 72 if self.cache_anonymous_only and has_vary_header(response, 'Cookie'): 73 assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware." 74 if request.user.is_authenticated(): 75 # Don't cache user-variable requests from authenticated users. 76 return False 77 return True 78 69 79 def process_response(self, request, response): 70 80 """Sets the cache, if needed.""" 71 if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache:81 if not self._should_update_cache(request, response): 72 82 # We don't need to update the cache, just return. 73 83 return response 74 84 if not response.status_code == 200: … … class FetchFromCacheMiddleware(object): 106 116 Checks whether the page is already cached and returns the cached 107 117 version if available. 108 118 """ 109 if self.cache_anonymous_only:110 assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware."111 112 119 if not request.method in ('GET', 'HEAD') or request.GET: 113 120 request._cache_update_cache = False 114 121 return None # Don't bother checking the cache. 115 122 116 if self.cache_anonymous_only and request.user.is_authenticated():117 request._cache_update_cache = False118 return None # Don't cache requests from authenticated users.119 120 123 # try and get the cached GET response 121 124 cache_key = get_cache_key(request, self.key_prefix, 'GET') 122 125 -
django/utils/cache.py
diff --git a/django/utils/cache.py b/django/utils/cache.py index b1b35b5..a2e7d6b 100644
a b def patch_vary_headers(response, newheaders): 134 134 if newheader.lower() not in existing_headers] 135 135 response['Vary'] = ', '.join(vary_headers + additional_headers) 136 136 137 def has_vary_header(response, header_query): 138 """ 139 Checks to see if the response has a given header name in its Vary header. 140 """ 141 if not response.has_header('Vary'): 142 return False 143 vary_headers = cc_delim_re.split(response['Vary']) 144 existing_headers = set([header.lower() for header in vary_headers]) 145 return header_query.lower() in existing_headers 146 137 147 def _i18n_cache_key_suffix(request, cache_key): 138 148 """If enabled, returns the cache key ending with a locale.""" 139 149 if settings.USE_I18N: -
docs/topics/cache.txt
diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt index f2b7a59..2fdc601 100644
a b Then, add the following required settings to your Django settings file: 323 323 collisions. Use an empty string if you don't care. 324 324 325 325 The cache middleware caches every page that doesn't have GET or POST 326 parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is327 ``True``, only anonymous requests (i.e., not those made by a logged-in user) 328 will be cached. This is a simple and effective way of disabling caching for any 329 user-specific pages (include Django's admin interface). Note that if you use330 ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated 331 ``AuthenticationMiddleware``. The cache middleware expects that a HEAD request 332 is answered with the same response headers exactly like the corresponding GET 333 request, in that case it could return cached GET response forHEAD request.326 parameters. Pages are cached separately based on the values of the HTTP headers 327 they vary by, so user-specific pages will never be shown to the wrong person if 328 you're accessing the user's information via 329 :attr:`request.user <django.http.HttpRequest.user>`, which results in the 330 appropriate ``Vary`` headers being set. The cache middleware expects that a HEAD 331 request is answered with the same response headers exactly like the 332 corresponding GET request, in that case it could return cached GET response for 333 HEAD request. 334 334 335 335 Additionally, the cache middleware automatically sets a few headers in each 336 336 ``HttpResponse``: -
tests/regressiontests/cache/tests.py
diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py index da4c9a8..ee9c272 100644
a b from django.core.cache import get_cache 15 15 from django.core.cache.backends.base import InvalidCacheBackendError, CacheKeyWarning 16 16 from django.http import HttpResponse, HttpRequest 17 17 from django.middleware.cache import FetchFromCacheMiddleware, UpdateCacheMiddleware 18 from django.test import TestCase 18 19 from django.utils import translation 19 20 from django.utils import unittest 20 from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key 21 from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key, has_vary_header 21 22 from django.utils.hashcompat import md5_constructor 22 23 from regressiontests.cache.models import Poll, expensive_calculation 23 24 … … class CacheUtils(unittest.TestCase): 544 545 patch_vary_headers(response, newheaders) 545 546 self.assertEqual(response['Vary'], resulting_vary) 546 547 548 def test_has_vary_header(self): 549 possible_headers = ('cookie', 'accept-encoding') 550 sample_values = ( 551 # Vary header value, has_vary_header value for the possible_headers 552 ('Cookie', (True, False)), 553 ('COOKIE', (True, False)), 554 ('Accept-Encoding', (False, True)), 555 ('Cookie, Accept-Encoding', (True, True)), 556 ('Accept-Encoding, Cookie', (True, True)), 557 ('Cookie , Accept-Encoding', (True, True)), 558 ) 559 for vary_header, results in sample_values: 560 response = HttpResponse() 561 response['Vary'] = vary_header 562 for test_header, result in zip(possible_headers, results): 563 self.assertEqual(has_vary_header(response, test_header), result) 564 547 565 def test_get_cache_key(self): 548 566 request = self._get_request(self.path) 549 567 response = HttpResponse() … … class CacheI18nTest(unittest.TestCase): 718 736 get_cache_data = FetchFromCacheMiddleware().process_request(request) 719 737 self.assertEqual(get_cache_data.content, es_message) 720 738 739 class CacheMiddlewareTests(TestCase): 740 urls = 'regressiontests.cache.urls' 741 742 def setUp(self): 743 self._orig_cache_middleware_anonymous_only = \ 744 getattr(settings, 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY', False) 745 self._orig_middleware_classes = settings.MIDDLEWARE_CLASSES 746 747 settings.MIDDLEWARE_CLASSES = list(settings.MIDDLEWARE_CLASSES) 748 settings.MIDDLEWARE_CLASSES.insert(0, 'django.middleware.cache.UpdateCacheMiddleware') 749 settings.MIDDLEWARE_CLASSES += ['django.middleware.cache.FetchFromCacheMiddleware'] 750 751 def tearDown(self): 752 settings.CACHE_MIDDLEWARE_ANONYMOUS_ONLY = self._orig_cache_middleware_anonymous_only 753 settings.MIDDLEWARE_CLASSES = self._orig_middleware_classes 754 755 def test_cache_middleware_anonymous_only_does_not_cause_vary_cookie(self): 756 settings.CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True 757 response = self.client.get('/') 758 self.failIf('Cookie' in response.get('Vary', '')) 759 760 721 761 if __name__ == '__main__': 722 762 unittest.main() -
new file tests/regressiontests/cache/urls.py
diff --git a/tests/regressiontests/cache/urls.py b/tests/regressiontests/cache/urls.py new file mode 100644 index 0000000..78b2125
- + 1 from django.conf.urls.defaults import * 2 3 4 urlpatterns = patterns('regressiontests.cache.views', 5 (r'^$', 'home'), 6 ) -
new file tests/regressiontests/cache/views.py
diff --git a/tests/regressiontests/cache/views.py b/tests/regressiontests/cache/views.py new file mode 100644 index 0000000..d8dc8b6
- + 1 from django.http import HttpResponse 2 3 4 def home(request): 5 return HttpResponse('Hello World!')