Skip to content

Commit c9fbc2c

Browse files
committed
Merge pull request #720 from tim-schilling/support-cache-page
Update the cache panel to support the cache_page decorator.
2 parents 872df6b + e6dfacc commit c9fbc2c

File tree

5 files changed

+40
-8
lines changed

5 files changed

+40
-8
lines changed

debug_toolbar/panels/cache.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
get_cache as original_get_cache)
1212
from django.core.cache.backends.base import BaseCache
1313
from django.dispatch import Signal
14+
from django.middleware import cache as middleware_cache
1415
from django.utils.translation import ugettext_lazy as _, ungettext
1516

1617

@@ -124,17 +125,28 @@ def get_cache(*args, **kwargs):
124125
return CacheStatTracker(original_get_cache(*args, **kwargs))
125126

126127

127-
def get_cache_handler():
128-
if CacheHandler is None:
129-
return None
130-
128+
if CacheHandler is not None:
131129
class CacheHandlerPatch(CacheHandler):
132130
def __getitem__(self, alias):
133131
actual_cache = super(CacheHandlerPatch, self).__getitem__(alias)
134132
return CacheStatTracker(actual_cache)
133+
134+
135+
def get_cache_handler():
136+
if CacheHandler is None:
137+
return None
135138
return CacheHandlerPatch()
136139

137140

141+
# Must monkey patch the middleware's cache module as well in order to
142+
# cover per-view level caching. This needs to be monkey patched outside
143+
# of the enable_instrumentation method since the django's
144+
# decorator_from_middleware_with_args will store the cache from core.caches
145+
# when it wraps the view.
146+
middleware_cache.get_cache = get_cache
147+
middleware_cache.caches = get_cache_handler()
148+
149+
138150
class CachePanel(Panel):
139151
"""
140152
Panel that displays the cache statistics.
@@ -212,19 +224,24 @@ def title(self):
212224
count) % dict(count=count)
213225

214226
def enable_instrumentation(self):
215-
# This isn't thread-safe because cache connections aren't thread-local
216-
# in Django, unlike database connections.
217227
cache.get_cache = get_cache
218228
if CacheHandler is None:
219229
cache.cache = CacheStatTracker(original_cache)
220230
else:
221-
cache.caches = get_cache_handler()
231+
if isinstance(middleware_cache.caches, CacheHandlerPatch):
232+
cache.caches = middleware_cache.caches
233+
else:
234+
cache.caches = get_cache_handler()
222235

223236
def disable_instrumentation(self):
224237
if CacheHandler is None:
225238
cache.cache = original_cache
226239
else:
227240
cache.caches = original_caches
241+
# While it can be restored to the original, any views that were
242+
# wrapped with the cache_page decorator will continue to use a
243+
# monkey patched cache.
244+
middleware_cache.caches = original_caches
228245
cache.get_cache = original_get_cache
229246

230247
def process_response(self, request, response):

docs/panels.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Cache
7575

7676
Path: ``debug_toolbar.panels.cache.CachePanel``
7777

78-
Cache queries.
78+
Cache queries. Is incompatible with Django's per-site caching.
7979

8080
Signal
8181
~~~~~~

tests/test_integration.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ def test_middleware_response_insertion(self):
8686
# check toolbar insertion before "</body>"
8787
self.assertContains(resp, '</div>\n</body>')
8888

89+
def test_cache_page(self):
90+
self.client.get('/cached_view/')
91+
self.assertEqual(
92+
len(self.toolbar.get_panel_by_id('CachePanel').calls), 3)
93+
self.client.get('/cached_view/')
94+
self.assertEqual(
95+
len(self.toolbar.get_panel_by_id('CachePanel').calls), 5)
96+
8997

9098
@override_settings(DEBUG=True)
9199
class DebugToolbarIntegrationTestCase(TestCase):

tests/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020
url(r'^non_ascii_request/$', 'regular_view', {'title': NonAsciiRepr()}),
2121
url(r'^new_user/$', 'new_user'),
2222
url(r'^execute_sql/$', 'execute_sql'),
23+
url(r'^cached_view/$', 'cached_view'),
2324
url(r'^__debug__/', include(debug_toolbar.urls)),
2425
)

tests/views.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.contrib.auth.models import User
66
from django.http import HttpResponse
77
from django.shortcuts import render
8+
from django.views.decorators.cache import cache_page
89

910

1011
def execute_sql(request):
@@ -24,3 +25,8 @@ def new_user(request, username='joe'):
2425
def resolving_view(request, arg1, arg2):
2526
# see test_url_resolving in tests.py
2627
return HttpResponse()
28+
29+
30+
@cache_page(60)
31+
def cached_view(request):
32+
return HttpResponse()

0 commit comments

Comments
 (0)