Skip to content

Commit

Permalink
panels(templates): avoid evaluating LazyObject
Browse files Browse the repository at this point in the history
LazyObject is typically used for something expensive to evaluate, so avoid evaluating it just for showing it in the debug toolbar.
  • Loading branch information
nijel committed Sep 19, 2023
1 parent 464c4f6 commit 39f3b6f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
7 changes: 6 additions & 1 deletion debug_toolbar/panels/templates/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,15 @@ def process_context_list(self, context_layers):
if pformatted is None:
temp_layer = {}
for key, value in context_layer.items():
# Do not force evaluating LazyObject
if hasattr(value, "_wrapped"):
# SimpleLazyObject has __repr__ which includes actual value
# if it has been already evaluated
temp_layer[key] = repr(value)
# Replace any request elements - they have a large
# Unicode representation and the request data is
# already made available from the Request panel.
if isinstance(value, http.HttpRequest):
elif isinstance(value, http.HttpRequest):
temp_layer[key] = "<<request>>"
# Replace the debugging sql_queries element. The SQL
# data is already made available from the SQL panel.
Expand Down
1 change: 1 addition & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Pending
* Removed outdated third-party panels from the list.
* Postponed context process in templates panel to include lazy evaluated
content.
* Fixed template panel to avoid evaluating ``LazyObject`` when not already evaluated.

4.2.0 (2023-08-10)
------------------
Expand Down
17 changes: 17 additions & 0 deletions tests/panels/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.contrib.auth.models import User
from django.template import Context, RequestContext, Template
from django.test import override_settings
from django.utils.functional import SimpleLazyObject

from ..base import BaseTestCase, IntegrationTestCase
from ..forms import TemplateReprForm
Expand Down Expand Up @@ -113,6 +114,22 @@ def test_empty_context(self):
["{'False': False, 'None': None, 'True': True}"],
)

def test_lazyobject(self):
response = self.panel.process_request(self.request)
t = Template("")
c = Context({"lazy": SimpleLazyObject(lambda: "lazy_value")})
t.render(c)
self.panel.generate_stats(self.request, response)
self.assertNotIn("lazy_value", self.panel.content)

def test_lazyobject_eval(self):
response = self.panel.process_request(self.request)
t = Template("{{lazy}}")
c = Context({"lazy": SimpleLazyObject(lambda: "lazy_value")})
self.assertEqual(t.render(c), "lazy_value")
self.panel.generate_stats(self.request, response)
self.assertIn("lazy_value", self.panel.content)


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

0 comments on commit 39f3b6f

Please sign in to comment.