Skip to content

Commit 39f3b6f

Browse files
committed
panels(templates): avoid evaluating LazyObject
LazyObject is typically used for something expensive to evaluate, so avoid evaluating it just for showing it in the debug toolbar.
1 parent 464c4f6 commit 39f3b6f

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

debug_toolbar/panels/templates/panel.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,15 @@ def process_context_list(self, context_layers):
133133
if pformatted is None:
134134
temp_layer = {}
135135
for key, value in context_layer.items():
136+
# Do not force evaluating LazyObject
137+
if hasattr(value, "_wrapped"):
138+
# SimpleLazyObject has __repr__ which includes actual value
139+
# if it has been already evaluated
140+
temp_layer[key] = repr(value)
136141
# Replace any request elements - they have a large
137142
# Unicode representation and the request data is
138143
# already made available from the Request panel.
139-
if isinstance(value, http.HttpRequest):
144+
elif isinstance(value, http.HttpRequest):
140145
temp_layer[key] = "<<request>>"
141146
# Replace the debugging sql_queries element. The SQL
142147
# data is already made available from the SQL panel.

docs/changes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Pending
77
* Removed outdated third-party panels from the list.
88
* Postponed context process in templates panel to include lazy evaluated
99
content.
10+
* Fixed template panel to avoid evaluating ``LazyObject`` when not already evaluated.
1011

1112
4.2.0 (2023-08-10)
1213
------------------

tests/panels/test_template.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.contrib.auth.models import User
33
from django.template import Context, RequestContext, Template
44
from django.test import override_settings
5+
from django.utils.functional import SimpleLazyObject
56

67
from ..base import BaseTestCase, IntegrationTestCase
78
from ..forms import TemplateReprForm
@@ -113,6 +114,22 @@ def test_empty_context(self):
113114
["{'False': False, 'None': None, 'True': True}"],
114115
)
115116

117+
def test_lazyobject(self):
118+
response = self.panel.process_request(self.request)
119+
t = Template("")
120+
c = Context({"lazy": SimpleLazyObject(lambda: "lazy_value")})
121+
t.render(c)
122+
self.panel.generate_stats(self.request, response)
123+
self.assertNotIn("lazy_value", self.panel.content)
124+
125+
def test_lazyobject_eval(self):
126+
response = self.panel.process_request(self.request)
127+
t = Template("{{lazy}}")
128+
c = Context({"lazy": SimpleLazyObject(lambda: "lazy_value")})
129+
self.assertEqual(t.render(c), "lazy_value")
130+
self.panel.generate_stats(self.request, response)
131+
self.assertIn("lazy_value", self.panel.content)
132+
116133

117134
@override_settings(
118135
DEBUG=True, DEBUG_TOOLBAR_PANELS=["debug_toolbar.panels.templates.TemplatesPanel"]

0 commit comments

Comments
 (0)