Ticket #15499: allow-cache-control-private-override-2.diff

File allow-cache-control-private-override-2.diff, 4.6 KB (added by AndiDog, 4 years ago)

Patch including tests and further documentation

  • django/utils/cache.py

     
    6767    if 'max-age' in cc and 'max_age' in kwargs:
    6868        kwargs['max_age'] = min(cc['max-age'], kwargs['max_age'])
    6969
     70    # Allow overriding private caching and vice versa
     71    if 'private' in cc and 'public' in kwargs:
     72        del cc['private']
     73    elif 'public' in cc and 'private' in kwargs:
     74        del cc['public']
     75
    7076    for (k, v) in kwargs.items():
    7177        cc[k.replace('_', '-')] = v
    7278    cc = ', '.join([dictvalue(el) for el in cc.items()])
  • docs/topics/cache.txt

     
    10581058This decorator takes care of sending out the appropriate HTTP header behind the
    10591059scenes.
    10601060
     1061Note that the cache control settings "private" and "public" are mutually
     1062exclusive. The decorator ensures that the "public" directive is removed if
     1063"private" should be set (and vice versa). An example use of the two directives
     1064would be a blog site that offers both private and public entries. Public
     1065entries may be cached on any shared cache. The following code uses
     1066``patch_cache_control``, the manual way to modify the cache control header
     1067(it is internally called by the ``cache_control`` decorator)::
     1068
     1069    from django.views.decorators.cache import patch_cache_control
     1070    from django.views.decorators.vary import vary_on_cookie
     1071
     1072    @vary_on_cookie
     1073    def list_blog_entries_view(request):
     1074        if request.user.is_anonymous():
     1075            response = render_only_public_entries()
     1076            patch_cache_control(response, public=True)
     1077        else:
     1078            response = render_private_and_public_entries(request.user)
     1079            patch_cache_control(response, private=True)
     1080
     1081        return response
     1082
    10611083There are a few other ways to control cache parameters. For example, HTTP
    10621084allows applications to do the following:
    10631085
  • tests/regressiontests/cache/tests.py

     
    44# Uses whatever cache backend is set in the test settings file.
    55
    66import os
     7import re
    78import tempfile
    89import time
    910import warnings
     
    1819from django.test.utils import get_warnings_state, restore_warnings_state
    1920from django.utils import translation
    2021from django.utils import unittest
    21 from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key
     22from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key, patch_cache_control
    2223from django.utils.hashcompat import md5_constructor
    2324from django.views.decorators.cache import cache_page
    2425
     
    932933        learn_cache_key(request, response)
    933934        self.assertEqual(get_cache_key(request), 'views.decorators.cache.cache_page.settingsprefix.HEAD.a8c87a3d8c44853d7f79474f7ffe4ad5.d41d8cd98f00b204e9800998ecf8427e')
    934935
     936    def test_patch_cache_control(self):
     937        tests = (
     938            # Initial Cache-Control, kwargs to patch_cache_control, expected Cache-Control parts
     939            (None, {"private" : True}, set(['private'])),
     940
     941            # Test whether private/public attributes are mutually exclusive
     942            ('private', {"private" : True}, set(['private'])),
     943            ('private', {"public" : True}, set(['public'])),
     944            ('public', {"private" : True}, set(['private'])),
     945            ('must-revalidate,max-age=60,private', {"public" : True}, set(['must-revalidate', 'max-age=60', 'public'])),
     946            ('must-revalidate,max-age=60,public', {"private" : True}, set(['must-revalidate', 'max-age=60', 'private'])),
     947
     948            ('public', {"public" : True}, set(['public'])),
     949            ('private', {"private" : True}, set(['private'])),
     950
     951            ('must-revalidate,max-age=60', {"public" : True}, set(['must-revalidate', 'max-age=60', 'public'])),
     952        )
     953
     954        cc_delim_re = re.compile(r'\s*,\s*')
     955
     956        for initial_cc, newheaders, expected_cc in tests:
     957            response = HttpResponse()
     958            if initial_cc is not None:
     959                response['Cache-Control'] = initial_cc
     960            patch_cache_control(response, **newheaders)
     961            parts = set(cc_delim_re.split(response['Cache-Control']))
     962            self.assertEqual(parts, expected_cc)
     963
    935964class PrefixedCacheUtils(CacheUtils):
    936965    def setUp(self):
    937966        super(PrefixedCacheUtils, self).setUp()
Back to Top