diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index de4ae9cf0..e7cd97f4d 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -38,8 +38,8 @@ def get_current(cls): return cls.debug_toolbars.get(thread.get_ident()) def __init__(self): - self.override_url = True - + self._urlconfs = {} + # Set method to use to decide to show toolbar self.show_toolbar = self._show_toolbar # default @@ -72,17 +72,27 @@ def _show_toolbar(self, request): def process_request(self, request): __traceback_hide__ = True if self.show_toolbar(request): - if self.override_url: + + urlconf_name = getattr(request, 'urlconf', settings.ROOT_URLCONF) + if urlconf_name not in self._urlconfs: + + import imp + original_urlconf = __import__(getattr(request, 'urlconf', settings.ROOT_URLCONF), {}, {}, ['*']) - debug_toolbar.urls.urlpatterns += patterns('', - ('', include(original_urlconf)), - ) + new_urlconf = imp.new_module('urlconf') + new_urlconf.urlpatterns = debug_toolbar.urls.urlpatterns + \ + patterns('', + ('', include(original_urlconf)), + ) + if hasattr(original_urlconf, 'handler404'): - debug_toolbar.urls.handler404 = original_urlconf.handler404 + new_urlconf.handler404 = original_urlconf.handler404 if hasattr(original_urlconf, 'handler500'): - debug_toolbar.urls.handler500 = original_urlconf.handler500 - self.override_url = False - request.urlconf = 'debug_toolbar.urls' + new_urlconf.handler500 = original_urlconf.handler500 + + self._urlconfs[urlconf_name] = new_urlconf + + request.urlconf = self._urlconfs[urlconf_name] toolbar = DebugToolbar(request) for panel in toolbar.panels: diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index 44b8b3e3e..19588e05b 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -9,30 +9,58 @@ from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel -# Code taken and adapted from Simon Willison and Django Snippets: -# http://www.djangosnippets.org/snippets/766/ - -# Monkeypatch instrumented test renderer from django.test.utils - we could use -# django.test.utils.setup_test_environment for this but that would also set up -# e-mail interception, which we don't want -from django.test.utils import instrumented_test_render -from django.template import Template - -if not hasattr(Template, '_render'): # Django < 1.2 - if Template.render != instrumented_test_render: - Template.original_render = Template.render - Template.render = instrumented_test_render -else: - if Template._render != instrumented_test_render: - Template.original_render = Template._render - Template._render = instrumented_test_render +def render_decorator(r): + """ + Decorate a Template's render function, r, to emit the signals + needed by DjDT. + """ + + def render(self, context): + template_rendered.send( + sender=self, template=self, context=context) + return r(self, context) + + render.decorated = True + + return render # MONSTER monkey-patch -old_template_init = Template.__init__ -def new_template_init(self, template_string, origin=None, name=''): - old_template_init(self, template_string, origin, name) - self.origin = origin -Template.__init__ = new_template_init +template_source_loaders = None +def find_template_and_decorate(name, dirs=None): + # Calculate template_source_loaders the first time the function is executed + # because putting this logic in the module-level namespace may cause + # circular import errors. See Django ticket #1292. + + from django.template.loader import find_template_loader, make_origin + from django.template import TemplateDoesNotExist + global template_source_loaders + if template_source_loaders is None: + loaders = [] + for loader_name in settings.TEMPLATE_LOADERS: + loader = find_template_loader(loader_name) + if loader is not None: + loaders.append(loader) + template_source_loaders = tuple(loaders) + for loader in template_source_loaders: + try: + source, display_name = loader(name, dirs) + + # see if this template has a render method, and if so + # decorate it to emit signals when rendering happens + if hasattr(source, 'render'): + if not hasattr(source.render, 'decorated'): + + # this class has not been decorated yet... + source.__class__.render = render_decorator( + source.__class__.render) + + return (source, make_origin(display_name, loader, name, dirs)) + except TemplateDoesNotExist: + pass + raise TemplateDoesNotExist(name) + +import django.template.loader +django.template.loader.find_template = find_template_and_decorate class TemplateDebugPanel(DebugPanel): """ @@ -71,14 +99,15 @@ def content(self): ] ) template_context = [] + for template_data in self.templates: info = {} # Clean up some info about templates template = template_data.get('template', None) # Skip templates that we are generating through the debug toolbar. - if template.name and template.name.startswith('debug_toolbar/'): + if hasattr(template, 'name') and template.name.startswith('debug_toolbar/'): continue - if template.origin and template.origin.name: + if hasattr(template, 'origin') and template.origin.name: template.origin_name = template.origin.name else: template.origin_name = 'No origin'