Ticket #16003: 16003.2.patch

File 16003.2.patch, 7.6 KB (added by Peter van Kampen, 13 years ago)

An updated patch /w tests

  • tests/regressiontests/cache/tests.py

     
    1515from django.core.cache.backends.base import CacheKeyWarning
    1616from django.http import HttpResponse, HttpRequest, QueryDict
    1717from django.middleware.cache import FetchFromCacheMiddleware, UpdateCacheMiddleware, CacheMiddleware
    18 from django.test import RequestFactory
     18from django.template import Template
     19from django.template.response import TemplateResponse
     20from django.test import RequestFactory, Client
    1921from django.test.utils import get_warnings_state, restore_warnings_state
    2022from django.utils import translation
    2123from django.utils import unittest
    22 from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key
     24from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key, patch_response_headers
    2325from django.views.decorators.cache import cache_page
    2426
    2527from regressiontests.cache.models import Poll, expensive_calculation
     
    14421444        response = other_with_timeout_view(request, '18')
    14431445        self.assertEqual(response.content, 'Hello World 18')
    14441446
     1447class TestWithTemplateResponse(unittest.TestCase):
     1448
     1449    """ Tests various headers w/ TemplateResponse.
     1450
     1451    Most are probably redundant since they manipulate the same object
     1452    anyway but the Etag header is 'special' because it relies on the
     1453    content being complete (which is not necessarily always the case
     1454    with a TemplateResponse)
     1455    """
     1456    def setUp(self):
     1457        self.path = '/cache/test/'
     1458        self.old_cache_middleware_key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
     1459        self.old_cache_middleware_seconds = settings.CACHE_MIDDLEWARE_SECONDS
     1460        self.orig_use_i18n = settings.USE_I18N
     1461        settings.CACHE_MIDDLEWARE_KEY_PREFIX = 'settingsprefix'
     1462        settings.CACHE_MIDDLEWARE_SECONDS = 1
     1463        settings.USE_I18N = False
     1464
     1465    def tearDown(self):
     1466        settings.CACHE_MIDDLEWARE_KEY_PREFIX = self.old_cache_middleware_key_prefix
     1467        settings.CACHE_MIDDLEWARE_SECONDS = self.old_cache_middleware_seconds
     1468        settings.USE_I18N = self.orig_use_i18n
     1469
     1470    def _get_request(self, path, method='GET'):
     1471        request = HttpRequest()
     1472        request.META = {
     1473            'SERVER_NAME': 'testserver',
     1474            'SERVER_PORT': 80,
     1475        }
     1476        request.method = method
     1477        request.path = request.path_info = "/cache/%s" % path
     1478        return request
     1479
     1480    def test_patch_vary_headers(self):
     1481        headers = (
     1482            # Initial vary, new headers, resulting vary.
     1483            (None, ('Accept-Encoding',), 'Accept-Encoding'),
     1484            ('Accept-Encoding', ('accept-encoding',), 'Accept-Encoding'),
     1485            ('Accept-Encoding', ('ACCEPT-ENCODING',), 'Accept-Encoding'),
     1486            ('Cookie', ('Accept-Encoding',), 'Cookie, Accept-Encoding'),
     1487            ('Cookie, Accept-Encoding', ('Accept-Encoding',), 'Cookie, Accept-Encoding'),
     1488            ('Cookie, Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'),
     1489            (None, ('Accept-Encoding', 'COOKIE'), 'Accept-Encoding, COOKIE'),
     1490            ('Cookie,     Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'),
     1491            ('Cookie    ,     Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'),
     1492        )
     1493        for initial_vary, newheaders, resulting_vary in headers:
     1494            response = TemplateResponse(HttpResponse(), Template("This is a test"))
     1495            if initial_vary is not None:
     1496                response['Vary'] = initial_vary
     1497            patch_vary_headers(response, newheaders)
     1498            self.assertEqual(response['Vary'], resulting_vary)
     1499
     1500    def test_get_cache_key(self):
     1501        request = self._get_request(self.path)
     1502        response = TemplateResponse(HttpResponse(), Template("This is a test"))
     1503        key_prefix = 'localprefix'
     1504        # Expect None if no headers have been set yet.
     1505        self.assertEqual(get_cache_key(request), None)
     1506        # Set headers to an empty list.
     1507        learn_cache_key(request, response)
     1508        self.assertEqual(get_cache_key(request), 'views.decorators.cache.cache_page.settingsprefix.GET.a8c87a3d8c44853d7f79474f7ffe4ad5.d41d8cd98f00b204e9800998ecf8427e')
     1509        # Verify that a specified key_prefix is taken into account.
     1510        learn_cache_key(request, response, key_prefix=key_prefix)
     1511        self.assertEqual(get_cache_key(request, key_prefix=key_prefix), 'views.decorators.cache.cache_page.localprefix.GET.a8c87a3d8c44853d7f79474f7ffe4ad5.d41d8cd98f00b204e9800998ecf8427e')
     1512
     1513    def test_get_cache_key_with_query(self):
     1514        request = self._get_request(self.path + '?test=1')
     1515        response = TemplateResponse(HttpResponse(), Template("This is a test"))
     1516        # Expect None if no headers have been set yet.
     1517        self.assertEqual(get_cache_key(request), None)
     1518        # Set headers to an empty list.
     1519        learn_cache_key(request, response)
     1520        # Verify that the querystring is taken into account.
     1521        self.assertEqual(get_cache_key(request), 'views.decorators.cache.cache_page.settingsprefix.GET.bd889c5a59603af44333ed21504db3cd.d41d8cd98f00b204e9800998ecf8427e')
     1522
     1523    def test_without_etag(self):
     1524        settings.USE_ETAGS = False
     1525        response = TemplateResponse(HttpResponse(), Template("This is a test"))
     1526        self.assertFalse(response.has_header('ETag'))
     1527        patch_response_headers(response)
     1528        self.assertFalse(response.has_header('ETag'))
     1529        response = response.render()
     1530        self.assertFalse(response.has_header('ETag'))
     1531       
     1532    def test_with_etag(self):
     1533        settings.USE_ETAGS = True
     1534        response = TemplateResponse(HttpResponse(), Template("This is a test"))
     1535        self.assertFalse(response.has_header('ETag'))
     1536        patch_response_headers(response)
     1537        self.assertFalse(response.has_header('ETag'))
     1538        response = response.render()
     1539        self.assertTrue(response.has_header('ETag'))
     1540
     1541class TestEtagWithAdmin(unittest.TestCase):
     1542    # See https://code.djangoproject.com/ticket/16003
     1543    def test_admin(self):
     1544        settings.USE_ETAGS = False
     1545        c = Client()
     1546        response = c.get('/test_admin/admin/')
     1547        self.assertEqual(response.status_code, 200)
     1548        self.assertFalse(response.has_header('ETag'))
     1549        settings.USE_ETAGS = True
     1550        c = Client()
     1551        response = c.get('/test_admin/admin/')
     1552        self.assertEqual(response.status_code, 200)
     1553        self.assertTrue(response.has_header('ETag'))
     1554
    14451555if __name__ == '__main__':
    14461556    unittest.main()
     1557   
  • django/utils/cache.py

     
    102102    if cache_timeout < 0:
    103103        cache_timeout = 0 # Can't have max-age negative
    104104    if settings.USE_ETAGS and not response.has_header('ETag'):
    105         response['ETag'] = '"%s"' % hashlib.md5(response.content).hexdigest()
     105        if hasattr(response, 'render') and callable(response.render):
     106            def callback(response):
     107                response['ETag'] = '"%s"' % hashlib.md5(response.content).hexdigest()
     108                return response
     109            response.add_post_render_callback(callback)
     110        else:
     111            response['ETag'] = '"%s"' % hashlib.md5(response.content).hexdigest()
    106112    if not response.has_header('Last-Modified'):
    107113        response['Last-Modified'] = http_date()
    108114    if not response.has_header('Expires'):
Back to Top