Skip to content

Commit 08bb474

Browse files
authored
Merge pull request #1282 from jdufresne/json-ajax
Make AJAX views return JSON instead of HTML
2 parents 3314bae + af0d5af commit 08bb474

File tree

9 files changed

+56
-29
lines changed

9 files changed

+56
-29
lines changed

debug_toolbar/panels/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ def content(self):
9494
if self.has_content:
9595
return render_to_string(self.template, self.get_stats())
9696

97+
@property
98+
def scripts(self):
99+
"""
100+
Scripts used by the HTML content of the panel when it's displayed.
101+
"""
102+
return []
103+
97104
# URLs for panel-specific views
98105

99106
@classmethod

debug_toolbar/panels/sql/views.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from django.http import HttpResponseBadRequest
2-
from django.template.response import SimpleTemplateResponse
1+
from django.http import HttpResponseBadRequest, JsonResponse
2+
from django.template.loader import render_to_string
33
from django.views.decorators.csrf import csrf_exempt
44

55
from debug_toolbar.decorators import require_show_toolbar
@@ -27,8 +27,8 @@ def sql_select(request):
2727
"headers": headers,
2828
"alias": form.cleaned_data["alias"],
2929
}
30-
# Using SimpleTemplateResponse avoids running global context processors.
31-
return SimpleTemplateResponse("debug_toolbar/panels/sql_select.html", context)
30+
content = render_to_string("debug_toolbar/panels/sql_select.html", context)
31+
return JsonResponse({"content": content})
3232
return HttpResponseBadRequest("Form errors")
3333

3434

@@ -64,8 +64,8 @@ def sql_explain(request):
6464
"headers": headers,
6565
"alias": form.cleaned_data["alias"],
6666
}
67-
# Using SimpleTemplateResponse avoids running global context processors.
68-
return SimpleTemplateResponse("debug_toolbar/panels/sql_explain.html", context)
67+
content = render_to_string("debug_toolbar/panels/sql_explain.html", context)
68+
return JsonResponse({"content": content})
6969
return HttpResponseBadRequest("Form errors")
7070

7171

@@ -115,6 +115,6 @@ def sql_profile(request):
115115
"headers": headers,
116116
"alias": form.cleaned_data["alias"],
117117
}
118-
# Using SimpleTemplateResponse avoids running global context processors.
119-
return SimpleTemplateResponse("debug_toolbar/panels/sql_profile.html", context)
118+
content = render_to_string("debug_toolbar/panels/sql_profile.html", context)
119+
return JsonResponse({"content": content})
120120
return HttpResponseBadRequest("Form errors")

debug_toolbar/panels/templates/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from django.core import signing
2-
from django.http import HttpResponseBadRequest
2+
from django.http import HttpResponseBadRequest, JsonResponse
33
from django.template import Origin, TemplateDoesNotExist
44
from django.template.engine import Engine
5-
from django.template.response import SimpleTemplateResponse
5+
from django.template.loader import render_to_string
66
from django.utils.safestring import mark_safe
77

88
from debug_toolbar.decorators import require_show_toolbar
@@ -57,8 +57,8 @@ def template_source(request):
5757
except ImportError:
5858
pass
5959

60-
# Using SimpleTemplateResponse avoids running global context processors.
61-
return SimpleTemplateResponse(
60+
content = render_to_string(
6261
"debug_toolbar/panels/template_source.html",
6362
{"source": source, "template_name": template_name},
6463
)
64+
return JsonResponse({"content": content})

debug_toolbar/panels/timer.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import time
22

33
from django.template.loader import render_to_string
4+
from django.templatetags.static import static
45
from django.utils.translation import gettext_lazy as _
56

67
from debug_toolbar.panels import Panel
@@ -51,6 +52,12 @@ def content(self):
5152
)
5253
return render_to_string(self.template, {"rows": rows})
5354

55+
@property
56+
def scripts(self):
57+
scripts = super().scripts
58+
scripts.append(static("debug_toolbar/js/toolbar.timer.js"))
59+
return scripts
60+
5461
def process_request(self, request):
5562
self._start_time = time.time()
5663
if self.has_content:

debug_toolbar/static/debug_toolbar/js/toolbar.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
const style = getComputedStyle(element);
2626
return style.display !== 'none';
2727
},
28-
executeScripts: function(root) {
29-
root.querySelectorAll('script').forEach(function(e) {
30-
const clone = document.createElement('script');
31-
clone.src = e.src;
32-
clone.async = true;
33-
root.appendChild(clone);
28+
executeScripts: function(scripts) {
29+
scripts.forEach(function(script) {
30+
const el = document.createElement('script');
31+
el.src = script;
32+
el.async = true;
33+
document.head.appendChild(el);
3434
});
3535
},
3636
};
@@ -45,7 +45,7 @@
4545
init = Object.assign({credentials: 'same-origin'}, init);
4646
return fetch(url, init).then(function(response) {
4747
if (response.ok) {
48-
return response.text();
48+
return response.json();
4949
} else {
5050
const win = document.querySelector('#djDebugWindow');
5151
win.innerHTML = '<div class="djDebugPanelTitle"><a class="djDebugClose" href="">»</a><h3>'+response.status+': '+response.statusText+'</h3></div>';
@@ -82,10 +82,10 @@
8282
url_params.append('store_id', store_id);
8383
url_params.append('panel_id', this.className);
8484
url += '?' + url_params.toString();
85-
ajax(url).then(function(body) {
85+
ajax(url).then(function(data) {
8686
inner.previousElementSibling.remove(); // Remove AJAX loader
87-
inner.innerHTML = body;
88-
$$.executeScripts(inner);
87+
inner.innerHTML = data.content;
88+
$$.executeScripts(data.scripts);
8989
});
9090
}
9191
}
@@ -121,10 +121,9 @@
121121
ajax_data.url = this.href;
122122
}
123123

124-
ajax(ajax_data.url, ajax_data).then(function(body) {
124+
ajax(ajax_data.url, ajax_data).then(function(data) {
125125
const win = djDebug.querySelector('#djDebugWindow');
126-
win.innerHTML = body;
127-
$$.executeScripts(win);
126+
win.innerHTML = data.content;
128127
$$.show(win);
129128
});
130129
});

debug_toolbar/templates/debug_toolbar/panels/timer.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% load i18n %}{% load static %}
1+
{% load i18n %}
22
<h4>{% trans "Resource usage" %}</h4>
33
<table>
44
<colgroup>
@@ -41,4 +41,3 @@ <h4>{% trans "Browser timing" %}</h4>
4141
</tbody>
4242
</table>
4343
</div>
44-
<script src="{% static 'debug_toolbar/js/toolbar.timer.js' %}" aysnc></script>

debug_toolbar/views.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from django.http import HttpResponse
1+
from django.http import JsonResponse
22
from django.utils.html import escape
33
from django.utils.translation import gettext as _
44

@@ -16,7 +16,9 @@ def render_panel(request):
1616
"Please reload the page and retry."
1717
)
1818
content = "<p>%s</p>" % escape(content)
19+
scripts = []
1920
else:
2021
panel = toolbar.get_panel_by_id(request.GET["panel_id"])
2122
content = panel.content
22-
return HttpResponse(content)
23+
scripts = panel.scripts
24+
return JsonResponse({"content": content, "scripts": scripts})

docs/changes.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@ UNRELEASED
88
* Updated the italian translation.
99
* Added support for Django 3.1a1.
1010
* Pruned unused CSS and removed hacks for ancient browsers.
11+
* Added the new :attr:`Panel.scripts <debug_toolbar.panels.Panel.scripts>`
12+
property. This property should return a list of JavaScript resources to be
13+
loaded in the browser when displaying the panel. Right now, this is used by a
14+
single panel, the Timer panel. Third party panels can use this property to
15+
add scripts rather then embedding them in the content HTML.
1116

17+
**Backwards incompatible changes**
18+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19+
20+
* Loading panel content no longer executes the scripts elements embedded in the
21+
HTML. Third party panels that require JavaScript resources should now use the
22+
:attr:`Panel.scripts <debug_toolbar.panels.Panel.scripts>` property.
1223

1324
2.2 (2020-01-31)
1425
----------------

docs/panels.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ unauthorized access. There is no public CSS API at this time.
319319

320320
.. autoattribute:: debug_toolbar.panels.Panel.content
321321

322+
.. autoattribute:: debug_toolbar.panels.Panel.scripts
323+
322324
.. automethod:: debug_toolbar.panels.Panel.get_urls
323325

324326
.. automethod:: debug_toolbar.panels.Panel.enable_instrumentation

0 commit comments

Comments
 (0)