Skip to content

Commit 89bac85

Browse files
committed
Extract output of context processors instead of recreating it.
Also include context processors explicitly passed to RequestContext. Fix #353.
1 parent 67c855a commit 89bac85

File tree

2 files changed

+56
-13
lines changed

2 files changed

+56
-13
lines changed

debug_toolbar/panels/templates/panel.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from __future__ import absolute_import, unicode_literals
22

3+
try:
4+
from collections import OrderedDict
5+
except ImportError:
6+
from django.utils.datastructures import SortedDict as OrderedDict
37
from os.path import normpath
48
from pprint import pformat
59

@@ -8,32 +12,58 @@
812
from django.conf import settings
913
from django.conf.urls import patterns, url
1014
from django.db.models.query import QuerySet, RawQuerySet
15+
from django.template import Context, RequestContext, Template
1116
from django.template.context import get_standard_processors
1217
from django.test.signals import template_rendered
18+
from django.test.utils import instrumented_test_render
1319
from django.utils.encoding import force_text
1420
from django.utils import six
1521
from django.utils.translation import ugettext_lazy as _
1622

1723
from debug_toolbar.panels import Panel
1824
from debug_toolbar.panels.sql.tracking import recording, SQLQueryTriggered
1925

20-
# Code taken and adapted from Simon Willison and Django Snippets:
21-
# http://www.djangosnippets.org/snippets/766/
2226

2327
# Monkey-patch to enable the template_rendered signal. The receiver returns
2428
# immediately when the panel is disabled to keep the overhead small.
2529

26-
from django.test.utils import instrumented_test_render
27-
from django.template import Template
30+
# Code taken and adapted from Simon Willison and Django Snippets:
31+
# http://www.djangosnippets.org/snippets/766/
2832

2933
if Template._render != instrumented_test_render:
3034
Template.original_render = Template._render
3135
Template._render = instrumented_test_render
3236

3337

38+
# Monkey-patch to store items added by template context processors. The
39+
# overhead is sufficiently small to justify enabling it unconditionally.
40+
41+
def _request_context__init__(
42+
self, request, dict_=None, processors=None, current_app=None,
43+
use_l10n=None, use_tz=None):
44+
Context.__init__(
45+
self, dict_, current_app=current_app,
46+
use_l10n=use_l10n, use_tz=use_tz)
47+
if processors is None:
48+
processors = ()
49+
else:
50+
processors = tuple(processors)
51+
self.context_processors = OrderedDict()
52+
updates = dict()
53+
for processor in get_standard_processors() + processors:
54+
name = '%s.%s' % (processor.__module__, processor.__name__)
55+
context = processor(request)
56+
self.context_processors[name] = context
57+
updates.update(context)
58+
self.update(updates)
59+
60+
RequestContext.__init__ = _request_context__init__
61+
62+
63+
# Monkey-patch versions of Django where Template doesn't store origin.
64+
# See https://code.djangoproject.com/ticket/16096.
65+
3466
if django.VERSION[:2] < (1, 7):
35-
# Monkey-patch versions of Django where Template doesn't store origin.
36-
# See https://code.djangoproject.com/ticket/16096.
3767

3868
old_template_init = Template.__init__
3969

@@ -107,6 +137,7 @@ def _store_template_info(self, sender, **kwargs):
107137
pass
108138

109139
kwargs['context'] = [force_text(item) for item in context_list]
140+
kwargs['context_processors'] = getattr(context, 'context_processors', None)
110141
self.templates.append(kwargs)
111142

112143
# Implement the Panel API
@@ -127,12 +158,6 @@ def get_urls(cls):
127158
)
128159

129160
def process_response(self, request, response):
130-
context_processors = dict(
131-
[
132-
("%s.%s" % (k.__module__, k.__name__),
133-
pformat(k(request))) for k in get_standard_processors()
134-
]
135-
)
136161
template_context = []
137162
for template_data in self.templates:
138163
info = {}
@@ -151,6 +176,12 @@ def process_response(self, request, response):
151176
info['context'] = '\n'.join(context_list)
152177
template_context.append(info)
153178

179+
# Fetch context_processors from any template
180+
if self.templates:
181+
context_processors = self.templates[0]['context_processors']
182+
else:
183+
context_processors = None
184+
154185
self.record_stats({
155186
'templates': template_context,
156187
'template_dirs': [normpath(x) for x in settings.TEMPLATE_DIRS],

tests/panels/test_template.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import django
66
from django.contrib.auth.models import User
7-
from django.template import Template, Context
7+
from django.template import Context, RequestContext, Template
88

99
from ..base import BaseTestCase
1010
from ..models import NonAsciiRepr
@@ -47,3 +47,15 @@ def test_object_with_non_ascii_repr_in_context(self):
4747
t.render(c)
4848
self.panel.process_response(self.request, self.response)
4949
self.assertIn('nôt åscíì', self.panel.content)
50+
51+
def test_custom_context_processor(self):
52+
self.panel.process_request(self.request)
53+
t = Template("{{ content }}")
54+
c = RequestContext(self.request, processors=[context_processor])
55+
t.render(c)
56+
self.panel.process_response(self.request, self.response)
57+
self.assertIn('tests.panels.test_template.context_processor', self.panel.content)
58+
59+
60+
def context_processor(request):
61+
return {'content': 'set by processor'}

0 commit comments

Comments
 (0)