Skip to content

Commit 71ce56c

Browse files
committed
Fix #1 -- subclassing the middleware instead of monkey-patching it
1 parent 3ee519a commit 71ce56c

File tree

4 files changed

+103
-91
lines changed

4 files changed

+103
-91
lines changed

README.rst

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Installation
1010

1111
#. Install and configure `Django Debug Toolbar <https://github.com/django-debug-toolbar/django-debug-toolbar>`_
1212

13-
#. Install `Django Debug Panel`::
13+
#. Install Django Debug Panel::
1414

1515
pip install django-debug-panel
1616

@@ -21,7 +21,25 @@ Installation
2121
'debug_panel',
2222
)
2323

24-
#. All the debug data of a request are stored into the cache backend ``debug-panel``
24+
#. Replace the Django Debug Toolbar middleware with the Django Debug Panel one. Replace::
25+
26+
MIDDLEWARE_CLASSES = (
27+
...
28+
'debug_toolbar.middleware.DebugToolbarMiddleware',
29+
...
30+
)
31+
32+
with::
33+
34+
MIDDLEWARE_CLASSES = (
35+
...
36+
'debug_panel.middleware.DebugPanelMiddleware',
37+
...
38+
)
39+
40+
41+
#. (Optional) Configure your cache.
42+
All the debug data of a request are stored into the cache backend ``debug-panel``
2543
if available. Otherwise, the ``default`` backend is used, and finally if no caches are
2644
defined it will fallback to a local memory cache.
2745
You might want to configure the ``debug-panel`` cache in your settings.py::
@@ -36,7 +54,6 @@ Installation
3654
'debug-panel': {
3755
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
3856
'LOCATION': '/var/tmp/debug-panel-cache',
39-
'TIMEOUT': 300,
4057
'OPTIONS': {
4158
'MAX_ENTRIES': 200
4259
}

debug_panel/__init__.py

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +0,0 @@
1-
from debug_toolbar.middleware import DebugToolbarMiddleware
2-
from django.core.urlresolvers import reverse, resolve, Resolver404
3-
from django.http import HttpResponseRedirect
4-
from django.shortcuts import render_to_response
5-
from django.views.static import serve
6-
import thread
7-
import time
8-
from .cache import cache
9-
10-
# the urls patterns that concern only the debug_panel application
11-
import urls as debug_panel_urlconf
12-
13-
debug_toolbar_process_request = DebugToolbarMiddleware.process_request
14-
15-
def process_request(self, request):
16-
"""
17-
Try to match the request with an URL from debug_panel application.
18-
19-
If it matches, that means we are serving a view from debug_panel,
20-
and we can skip the debug_toolbar middleware.
21-
22-
Otherwise we fallback to the default debug_toolbar middleware.
23-
"""
24-
25-
try:
26-
res = resolve(request.path, urlconf=debug_panel_urlconf)
27-
except Resolver404:
28-
return debug_toolbar_process_request(self, request)
29-
30-
return res.func(request, *res.args, **res.kwargs)
31-
32-
33-
def process_response(self, request, response):
34-
"""
35-
Since there is no hook to intercept and change rendering of the default
36-
debug_toolbar middleware, this is mostly a copy the original debug_toolbar
37-
middleware.
38-
39-
Instead of rendering the debug_toolbar inside the response HTML, it stored
40-
in the Django cache.
41-
42-
The data stored in the cache are then reachable from an URL that is appened
43-
to the HTTP response header under the 'X-debug-data-url' key.
44-
45-
"""
46-
47-
__traceback_hide__ = True
48-
49-
ident = thread.get_ident()
50-
toolbar = self.__class__.debug_toolbars.get(ident)
51-
52-
try:
53-
current_view = resolve(request.path)[0]
54-
except Resolver404:
55-
current_view = None
56-
57-
if current_view == serve or not toolbar:
58-
return response
59-
60-
if isinstance(response, HttpResponseRedirect):
61-
if not toolbar.config['INTERCEPT_REDIRECTS']:
62-
return response
63-
64-
redirect_to = response.get('Location', None)
65-
if redirect_to:
66-
cookies = response.cookies
67-
response = render_to_response(
68-
'debug_toolbar/redirect.html',
69-
{'redirect_to': redirect_to}
70-
)
71-
response.cookies = cookies
72-
73-
for panel in toolbar.panels:
74-
panel.process_response(request, response)
75-
76-
cache_key = "%f" % time.time()
77-
cache.set(cache_key, toolbar.render_toolbar())
78-
79-
response['X-debug-data-url'] = request.build_absolute_uri(
80-
reverse('debug_data', urlconf=debug_panel_urlconf, kwargs={'cache_key': cache_key}))
81-
82-
del self.__class__.debug_toolbars[ident]
83-
return response
84-
85-
DebugToolbarMiddleware.process_response = process_response
86-
DebugToolbarMiddleware.process_request = process_request

debug_panel/middleware.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""
2+
Debug Panel middleware
3+
"""
4+
from debug_toolbar.middleware import DebugToolbarMiddleware
5+
from django.core.urlresolvers import reverse, resolve, Resolver404
6+
from django.http import HttpResponseRedirect
7+
from django.shortcuts import render
8+
import threading
9+
import time
10+
from .cache import cache
11+
12+
# the urls patterns that concern only the debug_panel application
13+
import urls as debug_panel_urlconf
14+
15+
16+
class DebugPanelMiddleware(DebugToolbarMiddleware):
17+
"""
18+
Middleware to set up Debug Panel on incoming request and render toolbar
19+
on outgoing response.
20+
"""
21+
22+
23+
def process_request(self, request):
24+
"""
25+
Try to match the request with an URL from debug_panel application.
26+
27+
If it matches, that means we are serving a view from debug_panel,
28+
and we can skip the debug_toolbar middleware.
29+
30+
Otherwise we fallback to the default debug_toolbar middleware.
31+
"""
32+
33+
try:
34+
res = resolve(request.path, urlconf=debug_panel_urlconf)
35+
except Resolver404:
36+
return super(DebugPanelMiddleware, self).process_request(request)
37+
38+
return res.func(request, *res.args, **res.kwargs)
39+
40+
41+
def process_response(self, request, response):
42+
"""
43+
Since there is no hook to intercept and change rendering of the default
44+
debug_toolbar middleware, this is mostly a copy the original debug_toolbar
45+
middleware.
46+
47+
Instead of rendering the debug_toolbar inside the response HTML, it's stored
48+
in the Django cache.
49+
50+
The data stored in the cache are then reachable from an URL that is appened
51+
to the HTTP response header under the 'X-debug-data-url' key.
52+
"""
53+
__traceback_hide__ = True
54+
ident = threading.current_thread().ident
55+
toolbar = self.__class__.debug_toolbars.get(ident)
56+
if not toolbar or request.is_ajax() or getattr(response, 'streaming', False):
57+
return response
58+
if isinstance(response, HttpResponseRedirect):
59+
if not toolbar.config['INTERCEPT_REDIRECTS']:
60+
return response
61+
redirect_to = response.get('Location', None)
62+
if redirect_to:
63+
cookies = response.cookies
64+
response = render(
65+
request,
66+
'debug_toolbar/redirect.html',
67+
{'redirect_to': redirect_to}
68+
)
69+
response.cookies = cookies
70+
71+
for panel in toolbar.panels:
72+
panel.process_response(request, response)
73+
74+
cache_key = "%f" % time.time()
75+
cache.set(cache_key, toolbar.render_toolbar())
76+
77+
response['X-debug-data-url'] = request.build_absolute_uri(
78+
reverse('debug_data', urlconf=debug_panel_urlconf, kwargs={'cache_key': cache_key}))
79+
80+
del self.__class__.debug_toolbars[ident]
81+
return response

debug_panel/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
URLpatterns for the debug toolbar.
2+
URLpatterns for the debug panel.
33
44
These should not be loaded explicitly; It is used internally by the
55
debug-panel application.
@@ -13,4 +13,4 @@
1313

1414
urlpatterns = patterns('debug_panel.views',
1515
url(r'^%s/data/(?P<cache_key>\d+\.\d+)/$' % _PREFIX, 'debug_data', name='debug_data'),
16-
)
16+
)

0 commit comments

Comments
 (0)