diff -r 9b484f4bd7e0 django/middleware/cache.py
|
a
|
b
|
|
| 50 | 50 | |
| 51 | 51 | from django.conf import settings |
| 52 | 52 | from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS |
| | 53 | from django.http import HttpResponse |
| 53 | 54 | from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age |
| 54 | 55 | |
| | 56 | def cache_templateresponse_cb(cache_obj, cache_key, timeout): |
| | 57 | """Callback for TemplateResponse objects to cache a plain HttpResponse |
| | 58 | object upon rendering.""" |
| | 59 | def __callback__(response): |
| | 60 | plain_response = HttpResponse() |
| | 61 | for attr in ['status_code', '_headers', '_charset', '_container', |
| | 62 | '_is_string', 'cookies']: |
| | 63 | setattr(plain_response, attr, getattr(response, attr)) |
| | 64 | cache_obj.set(cache_key, plain_response, timeout) |
| | 65 | return plain_response |
| | 66 | return __callback__ |
| | 67 | |
| 55 | 68 | class UpdateCacheMiddleware(object): |
| 56 | 69 | """ |
| 57 | 70 | Response-phase cache middleware that updates the cache if the response is |
| … |
… |
|
| 86 | 99 | patch_response_headers(response, timeout) |
| 87 | 100 | if timeout: |
| 88 | 101 | cache_key = learn_cache_key(request, response, timeout, self.key_prefix, cache=self.cache) |
| 89 | | self.cache.set(cache_key, response, timeout) |
| | 102 | if hasattr(response, 'render') and callable(response.render): |
| | 103 | response.post_render_callback = cache_templateresponse_cb( |
| | 104 | self.cache, cache_key, timeout) |
| | 105 | else: |
| | 106 | self.cache.set(cache_key, response, timeout) |
| 90 | 107 | return response |
| 91 | 108 | |
| 92 | 109 | class FetchFromCacheMiddleware(object): |
diff -r 9b484f4bd7e0 django/template/response.py
|
a
|
b
|
|
| 65 | 65 | Returns the baked response instance. |
| 66 | 66 | """ |
| 67 | 67 | if not self._is_rendered: |
| | 68 | if callable(self.pre_render_callback): |
| | 69 | self.pre_render_callback(self) |
| 68 | 70 | self._set_content(self.rendered_content) |
| | 71 | if callable(self.post_render_callback): |
| | 72 | self.post_render_callback(self) |
| 69 | 73 | return self |
| 70 | 74 | |
| 71 | 75 | is_rendered = property(lambda self: self._is_rendered) |
| 72 | 76 | |
| | 77 | pre_render_callback = None |
| | 78 | post_render_callback = None |
| | 79 | |
| 73 | 80 | def __iter__(self): |
| 74 | 81 | if not self._is_rendered: |
| 75 | 82 | raise ContentNotRenderedError('The response content must be rendered before it can be iterated over.') |
| … |
… |
|
| 109 | 116 | return context |
| 110 | 117 | else: |
| 111 | 118 | return RequestContext(self._request, context, current_app=self._current_app) |
| | 119 | |
| | 120 | |
diff -r 9b484f4bd7e0 tests/regressiontests/generic_views/base.py
|
a
|
b
|
|
| | 1 | import time |
| 1 | 2 | import unittest |
| 2 | 3 | |
| 3 | 4 | from django.core.exceptions import ImproperlyConfigured |
| … |
… |
|
| 158 | 159 | def _assert_about(self, response): |
| 159 | 160 | response.render() |
| 160 | 161 | self.assertEqual(response.status_code, 200) |
| 161 | | self.assertEqual(response.content, '<h1>About</h1>') |
| | 162 | self.assertContains(response, '<h1>About</h1>') |
| 162 | 163 | |
| 163 | 164 | def test_get(self): |
| 164 | 165 | """ |
| … |
… |
|
| 197 | 198 | self.assertEqual(response.context['params'], {'foo': 'bar'}) |
| 198 | 199 | self.assertEqual(response.context['key'], 'value') |
| 199 | 200 | |
| | 201 | def test_cached_views(self): |
| | 202 | """ |
| | 203 | A template view can be cached |
| | 204 | """ |
| | 205 | response = self.client.get('/template/cached/bar/') |
| | 206 | self.assertEqual(response.status_code, 200) |
| | 207 | |
| | 208 | time.sleep(0.2) |
| | 209 | |
| | 210 | response2 = self.client.get('/template/cached/bar/') |
| | 211 | self.assertEqual(response2.status_code, 200) |
| | 212 | |
| | 213 | self.assertEqual(response.content, response2.content) |
| | 214 | |
| | 215 | time.sleep(1.0) |
| | 216 | |
| | 217 | # Let the cache expire and test again |
| | 218 | response2 = self.client.get('/template/cached/bar/') |
| | 219 | self.assertEqual(response2.status_code, 200) |
| | 220 | |
| | 221 | self.assertNotEqual(response.content, response2.content) |
| | 222 | |
| 200 | 223 | class RedirectViewTest(unittest.TestCase): |
| 201 | 224 | rf = RequestFactory() |
| 202 | 225 | |
diff -r 9b484f4bd7e0 tests/regressiontests/generic_views/templates/generic_views/about.html
|
a
|
b
|
|
| 1 | | <h1>About</h1> |
| 2 | | No newline at end of file |
| | 1 | <h1>About</h1> |
| | 2 | {% now "U.u" %} |
diff -r 9b484f4bd7e0 tests/regressiontests/generic_views/urls.py
|
a
|
b
|
|
| 1 | 1 | from django.conf.urls.defaults import * |
| 2 | 2 | from django.views.generic import TemplateView |
| | 3 | from django.views.decorators.cache import cache_page |
| 3 | 4 | |
| 4 | 5 | import views |
| 5 | 6 | |
| … |
… |
|
| 15 | 16 | (r'^template/custom/(?P<foo>\w+)/$', |
| 16 | 17 | views.CustomTemplateView.as_view(template_name='generic_views/about.html')), |
| 17 | 18 | |
| | 19 | (r'^template/cached/(?P<foo>\w+)/$', |
| | 20 | cache_page(TemplateView.as_view(template_name='generic_views/about.html'), 1)), |
| | 21 | |
| 18 | 22 | # DetailView |
| 19 | 23 | (r'^detail/obj/$', |
| 20 | 24 | views.ObjectDetail.as_view()), |