From 97fa2e5310116189ec3224196c37aac2f0ec76a7 Mon Sep 17 00:00:00 2001 From: "Bart K. de Koning" Date: Fri, 7 Jun 2024 16:20:55 -0400 Subject: [PATCH 1/8] Fixed issue #1682 -- alert user when using file field without proper encoding --- debug_toolbar/panels/alerts.py | 95 +++++++++++++++++++ debug_toolbar/settings.py | 1 + .../debug_toolbar/panels/alerts.html | 12 +++ docs/changes.rst | 2 + docs/configuration.rst | 1 + docs/panels.rst | 9 ++ tests/panels/test_alerts.py | 57 +++++++++++ tests/panels/test_history.py | 1 + 8 files changed, 178 insertions(+) create mode 100644 debug_toolbar/panels/alerts.py create mode 100644 debug_toolbar/templates/debug_toolbar/panels/alerts.html create mode 100644 tests/panels/test_alerts.py diff --git a/debug_toolbar/panels/alerts.py b/debug_toolbar/panels/alerts.py new file mode 100644 index 000000000..e520c67d8 --- /dev/null +++ b/debug_toolbar/panels/alerts.py @@ -0,0 +1,95 @@ +from html.parser import HTMLParser + +from django.utils.translation import gettext_lazy as _ + +from debug_toolbar.panels import Panel + + +class FormParser(HTMLParser): + """ + HTML form parser, used to check for invalid configurations of forms that + take file inputs. + """ + + def __init__(self): + super().__init__() + self.in_form = False + self.current_form = {} + self.forms = [] + + def handle_starttag(self, tag, attrs): + attrs = dict(attrs) + if tag == "form": + self.in_form = True + self.current_form = { + "file_form": False, + "form_attrs": attrs, + "submit_element_attrs": [], + } + elif self.in_form and tag == "input" and attrs.get("type") == "file": + self.current_form["file_form"] = True + elif self.in_form and ( + (tag == "input" and attrs.get("type") in {"submit", "image"}) + or tag == "button" + ): + self.current_form["submit_element_attrs"].append(attrs) + + def handle_endtag(self, tag): + if tag == "form" and self.in_form: + self.forms.append(self.current_form) + self.in_form = False + + +class AlertsPanel(Panel): + """ + A panel to alert users to issues. + """ + + title = _("Alerts") + + template = "debug_toolbar/panels/alerts.html" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.issues = [] + + @property + def nav_subtitle(self): + if self.issues: + issue_text = "issue" if len(self.issues) == 1 else "issues" + return f"{len(self.issues)} {issue_text} found" + else: + return "" + + def add_issue(self, issue): + self.issues.append(issue) + + def check_invalid_file_form_configuration(self, html_content): + parser = FormParser() + parser.feed(html_content) + + for form in parser.forms: + if ( + form["file_form"] + and form["form_attrs"].get("enctype") != "multipart/form-data" + and not any( + elem.get("formenctype") == "multipart/form-data" + for elem in form["submit_element_attrs"] + ) + ): + form_id = form["form_attrs"].get("id", "no form id") + issue = ( + f'Form with id "{form_id}" contains file input but ' + "does not have multipart/form-data encoding." + ) + self.add_issue({"issue": issue}) + return self.issues + + def generate_stats(self, request, response): + html_content = response.content.decode(response.charset) + self.check_invalid_file_form_configuration(html_content) + + # Further issue checks can go here + + # Write all issues to record_stats + self.record_stats({"issues": self.issues}) diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py index ca7036c34..0fb3f81c5 100644 --- a/debug_toolbar/settings.py +++ b/debug_toolbar/settings.py @@ -58,6 +58,7 @@ def get_config(): PANELS_DEFAULTS = [ + "debug_toolbar.panels.alerts.AlertsPanel", "debug_toolbar.panels.history.HistoryPanel", "debug_toolbar.panels.versions.VersionsPanel", "debug_toolbar.panels.timer.TimerPanel", diff --git a/debug_toolbar/templates/debug_toolbar/panels/alerts.html b/debug_toolbar/templates/debug_toolbar/panels/alerts.html new file mode 100644 index 000000000..c13e96249 --- /dev/null +++ b/debug_toolbar/templates/debug_toolbar/panels/alerts.html @@ -0,0 +1,12 @@ +{% load i18n %} + +{% if issues %} +

{% trans "Issues found" %}

+ {% for issue in issues %} + + {% endfor %} +{% else %} +

No issues found.

+{% endif %} diff --git a/docs/changes.rst b/docs/changes.rst index 2eaece240..2a4a52ac9 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -4,6 +4,8 @@ Change log Pending ------- +* Added alert panel with warning when form is using file fields + without proper encoding type. * Fixed overriding font-family for both light and dark themes. * Restored compatibility with ``iptools.IpRangeList``. diff --git a/docs/configuration.rst b/docs/configuration.rst index 04694aceb..1ae9c05a8 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -20,6 +20,7 @@ included in the toolbar. It works like Django's ``MIDDLEWARE`` setting. The default value is:: DEBUG_TOOLBAR_PANELS = [ + 'debug_toolbar.panels.alerts.AlertsPanel', 'debug_toolbar.panels.history.HistoryPanel', 'debug_toolbar.panels.versions.VersionsPanel', 'debug_toolbar.panels.timer.TimerPanel', diff --git a/docs/panels.rst b/docs/panels.rst index 33359ea46..b6e4cdac1 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -9,6 +9,15 @@ Default built-in panels The following panels are enabled by default. +Alerts +~~~~~~~ + +.. class:: debug_toolbar.panels.alerts.AlertsPanel + +This panel shows alerts for a set of pre-defined issues. Currently, the only +issue it checks for is the encoding of a form that takes a file input not +being set to ``multipart/form-data``. + History ~~~~~~~ diff --git a/tests/panels/test_alerts.py b/tests/panels/test_alerts.py new file mode 100644 index 000000000..e1f1948c5 --- /dev/null +++ b/tests/panels/test_alerts.py @@ -0,0 +1,57 @@ +from django.http import HttpResponse +from django.template import Context, Template + +from ..base import BaseTestCase + + +class AlertsPanelTestCase(BaseTestCase): + panel_id = "AlertsPanel" + + def test_issue_warning_display(self): + """ + Test that the panel (does not) display[s] a warning when there are + (no) issues. + """ + self.panel.issues = 0 + nav_subtitle = self.panel.nav_subtitle + self.assertNotIn("issues found", nav_subtitle) + + self.panel.issues = ["Issue 1", "Issue 2"] + nav_subtitle = self.panel.nav_subtitle + self.assertIn("2 issues found", nav_subtitle) + + def test_file_form_without_enctype_multipart_form_data(self): + """ + Test that the panel displays a form invalid message when there is + a file input but encoding not set to multipart/form-data. + """ + test_form = '
' + result = self.panel.check_invalid_file_form_configuration(test_form) + expected_error = ( + 'Form with id "test-form" contains file input ' + "but does not have multipart/form-data encoding." + ) + self.assertEqual(result[0]["issue"], expected_error) + self.assertEqual(len(result), 1) + + def test_file_form_with_enctype_multipart_form_data(self): + test_form = """
+ +
""" + result = self.panel.check_invalid_file_form_configuration(test_form) + + self.assertEqual(len(result), 0) + + def test_integration_file_form_without_enctype_multipart_form_data(self): + t = Template('
') + c = Context({}) + rendered_template = t.render(c) + response = HttpResponse(content=rendered_template) + + self.panel.generate_stats(self.request, response) + + self.assertIn( + "Form with id "test-form" contains file input " + "but does not have multipart/form-data encoding.", + self.panel.content, + ) diff --git a/tests/panels/test_history.py b/tests/panels/test_history.py index 2e0aa2179..43e80c077 100644 --- a/tests/panels/test_history.py +++ b/tests/panels/test_history.py @@ -67,6 +67,7 @@ def test_urls(self): @override_settings(DEBUG=True) class HistoryViewsTestCase(IntegrationTestCase): PANEL_KEYS = { + "AlertsPanel", "VersionsPanel", "TimerPanel", "SettingsPanel", From 00dc7656e9f290ee7e49a7eaea3bded7b4c3d712 Mon Sep 17 00:00:00 2001 From: "Bart K. de Koning" Date: Sat, 8 Jun 2024 14:12:57 -0400 Subject: [PATCH 2/8] Changed issues to alerts, added docstring to check_invalid_... function, changed call in nav_subtitle to get_stats --- debug_toolbar/panels/alerts.py | 30 +++++++++++-------- .../debug_toolbar/panels/alerts.html | 10 +++---- tests/panels/test_alerts.py | 19 ++++++------ 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/debug_toolbar/panels/alerts.py b/debug_toolbar/panels/alerts.py index e520c67d8..c6e6d932a 100644 --- a/debug_toolbar/panels/alerts.py +++ b/debug_toolbar/panels/alerts.py @@ -51,20 +51,26 @@ class AlertsPanel(Panel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.issues = [] + self.alerts = [] @property def nav_subtitle(self): - if self.issues: - issue_text = "issue" if len(self.issues) == 1 else "issues" - return f"{len(self.issues)} {issue_text} found" + alerts = self.get_stats()["alerts"] + if alerts: + alert_text = "alert" if len(alerts) == 1 else "alerts" + return f"{len(alerts)} {alert_text}" else: return "" - def add_issue(self, issue): - self.issues.append(issue) + def add_alert(self, alert): + self.alerts.append(alert) def check_invalid_file_form_configuration(self, html_content): + """ + Inspects HTML content for a form that includes a file input but does + not have the encoding type set to multipart/form-data, and warns the + user if so. + """ parser = FormParser() parser.feed(html_content) @@ -78,18 +84,18 @@ def check_invalid_file_form_configuration(self, html_content): ) ): form_id = form["form_attrs"].get("id", "no form id") - issue = ( + alert = ( f'Form with id "{form_id}" contains file input but ' "does not have multipart/form-data encoding." ) - self.add_issue({"issue": issue}) - return self.issues + self.add_alert({"alert": alert}) + return self.alerts def generate_stats(self, request, response): html_content = response.content.decode(response.charset) self.check_invalid_file_form_configuration(html_content) - # Further issue checks can go here + # Further alert checks can go here - # Write all issues to record_stats - self.record_stats({"issues": self.issues}) + # Write all alerts to record_stats + self.record_stats({"alerts": self.alerts}) diff --git a/debug_toolbar/templates/debug_toolbar/panels/alerts.html b/debug_toolbar/templates/debug_toolbar/panels/alerts.html index c13e96249..b78d3d521 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/alerts.html +++ b/debug_toolbar/templates/debug_toolbar/panels/alerts.html @@ -1,12 +1,12 @@ {% load i18n %} -{% if issues %} -

{% trans "Issues found" %}

- {% for issue in issues %} +{% if alerts %} +

{% trans "alerts found" %}

+ {% for alert in alerts %} {% endfor %} {% else %} -

No issues found.

+

No alerts found.

{% endif %} diff --git a/tests/panels/test_alerts.py b/tests/panels/test_alerts.py index e1f1948c5..e792aed6c 100644 --- a/tests/panels/test_alerts.py +++ b/tests/panels/test_alerts.py @@ -7,18 +7,16 @@ class AlertsPanelTestCase(BaseTestCase): panel_id = "AlertsPanel" - def test_issue_warning_display(self): + def test_alert_warning_display(self): """ - Test that the panel (does not) display[s] a warning when there are - (no) issues. + Test that the panel (does not) display[s] an alert when there are + (no) problems. """ - self.panel.issues = 0 - nav_subtitle = self.panel.nav_subtitle - self.assertNotIn("issues found", nav_subtitle) + self.panel.record_stats({"alerts": []}) + self.assertNotIn("alerts", self.panel.nav_subtitle) - self.panel.issues = ["Issue 1", "Issue 2"] - nav_subtitle = self.panel.nav_subtitle - self.assertIn("2 issues found", nav_subtitle) + self.panel.record_stats({"alerts": ["Alert 1", "Alert 2"]}) + self.assertIn("2 alerts", self.panel.nav_subtitle) def test_file_form_without_enctype_multipart_form_data(self): """ @@ -31,7 +29,7 @@ def test_file_form_without_enctype_multipart_form_data(self): 'Form with id "test-form" contains file input ' "but does not have multipart/form-data encoding." ) - self.assertEqual(result[0]["issue"], expected_error) + self.assertEqual(result[0]["alert"], expected_error) self.assertEqual(len(result), 1) def test_file_form_with_enctype_multipart_form_data(self): @@ -50,6 +48,7 @@ def test_integration_file_form_without_enctype_multipart_form_data(self): self.panel.generate_stats(self.request, response) + self.assertIn("1 alert", self.panel.nav_subtitle) self.assertIn( "Form with id "test-form" contains file input " "but does not have multipart/form-data encoding.", From 0bbb66dca799577697d02ab0628b3938db552c59 Mon Sep 17 00:00:00 2001 From: "Bart K. de Koning" <118313986+bkdekoning@users.noreply.github.com> Date: Sat, 8 Jun 2024 11:57:03 -0400 Subject: [PATCH 3/8] Update AlertsPanel documentation to list pre-defined alert cases Co-authored-by: Tim Schilling --- docs/panels.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/panels.rst b/docs/panels.rst index b6e4cdac1..41d82b370 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -14,9 +14,11 @@ Alerts .. class:: debug_toolbar.panels.alerts.AlertsPanel -This panel shows alerts for a set of pre-defined issues. Currently, the only -issue it checks for is the encoding of a form that takes a file input not -being set to ``multipart/form-data``. +This panel shows alerts for a set of pre-defined cases: + +- Alerts when the response has a form without the + ``enctype="multipart/form-data"`` attribute and the form contains + a file input History ~~~~~~~ From c332a6f99bc3b0919181de2080d3a3c5ba9903bc Mon Sep 17 00:00:00 2001 From: "Bart K. de Koning" Date: Tue, 11 Jun 2024 11:57:55 -0400 Subject: [PATCH 4/8] added check for file inputs that directly reference a form, including tests; also added tests for setting encoding in submit input type --- debug_toolbar/panels/alerts.py | 43 ++++++++++++++++++++++++++++++---- tests/panels/test_alerts.py | 29 +++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/debug_toolbar/panels/alerts.py b/debug_toolbar/panels/alerts.py index c6e6d932a..352e72ef3 100644 --- a/debug_toolbar/panels/alerts.py +++ b/debug_toolbar/panels/alerts.py @@ -16,23 +16,39 @@ def __init__(self): self.in_form = False self.current_form = {} self.forms = [] + self.form_ids = [] + self.referenced_file_inputs = [] def handle_starttag(self, tag, attrs): attrs = dict(attrs) if tag == "form": self.in_form = True + form_id = attrs.get("id") + if form_id: + self.form_ids.append(form_id) self.current_form = { "file_form": False, "form_attrs": attrs, "submit_element_attrs": [], } - elif self.in_form and tag == "input" and attrs.get("type") == "file": + elif ( + self.in_form + and tag == "input" + and attrs.get("type") == "file" + and (not attrs.get("form") or attrs.get("form") == "") + ): self.current_form["file_form"] = True - elif self.in_form and ( - (tag == "input" and attrs.get("type") in {"submit", "image"}) - or tag == "button" + elif ( + self.in_form + and ( + (tag == "input" and attrs.get("type") in {"submit", "image"}) + or tag == "button" + ) + and (not attrs.get("form") or attrs.get("form") == "") ): self.current_form["submit_element_attrs"].append(attrs) + elif tag == "input" and attrs.get("form"): + self.referenced_file_inputs.append(attrs) def handle_endtag(self, tag): if tag == "form" and self.in_form: @@ -74,6 +90,8 @@ def check_invalid_file_form_configuration(self, html_content): parser = FormParser() parser.feed(html_content) + # Check for file inputs directly inside a form that do not reference + # any form through the form attribute for form in parser.forms: if ( form["file_form"] @@ -89,6 +107,23 @@ def check_invalid_file_form_configuration(self, html_content): "does not have multipart/form-data encoding." ) self.add_alert({"alert": alert}) + + # Check for file inputs that reference a form + form_attrs_by_id = { + form["form_attrs"].get("id"): form["form_attrs"] for form in parser.forms + } + + for attrs in parser.referenced_file_inputs: + form_id = attrs.get("form") + if form_id and attrs.get("type") == "file": + form_attrs = form_attrs_by_id.get(form_id) + if form_attrs and form_attrs.get("enctype") != "multipart/form-data": + alert = ( + f'Input element references form with id "{form_id}" ' + "but the form does not have multipart/form-data encoding." + ) + self.add_alert({"alert": alert}) + return self.alerts def generate_stats(self, request, response): diff --git a/tests/panels/test_alerts.py b/tests/panels/test_alerts.py index e792aed6c..43e9b7328 100644 --- a/tests/panels/test_alerts.py +++ b/tests/panels/test_alerts.py @@ -40,6 +40,35 @@ def test_file_form_with_enctype_multipart_form_data(self): self.assertEqual(len(result), 0) + def test_file_form_with_enctype_multipart_form_data_in_button(self): + test_form = """
+ + +
""" + result = self.panel.check_invalid_file_form_configuration(test_form) + + self.assertEqual(len(result), 0) + + def test_referenced_file_input_without_enctype_multipart_form_data(self): + test_file_input = """
+ """ + result = self.panel.check_invalid_file_form_configuration(test_file_input) + + expected_error = ( + 'Input element references form with id "test-form" ' + "but the form does not have multipart/form-data encoding." + ) + self.assertEqual(result[0]["alert"], expected_error) + self.assertEqual(len(result), 1) + + def test_referenced_file_input_with_enctype_multipart_form_data(self): + test_file_input = """
+
+ """ + result = self.panel.check_invalid_file_form_configuration(test_file_input) + + self.assertEqual(len(result), 0) + def test_integration_file_form_without_enctype_multipart_form_data(self): t = Template('
') c = Context({}) From d89ee7363e9aa577f78d4dfce16b518eedc6c223 Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Wed, 3 Jul 2024 11:53:30 -0500 Subject: [PATCH 5/8] Update the alert messages to be on the panel as a map. This also explicitly mentions what attribute the form needs in the message. --- debug_toolbar/panels/alerts.py | 28 +++++++++++++------ .../debug_toolbar/panels/alerts.html | 4 +-- tests/panels/test_alerts.py | 28 +++++++++++++++---- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/debug_toolbar/panels/alerts.py b/debug_toolbar/panels/alerts.py index 352e72ef3..27a7119ee 100644 --- a/debug_toolbar/panels/alerts.py +++ b/debug_toolbar/panels/alerts.py @@ -61,6 +61,18 @@ class AlertsPanel(Panel): A panel to alert users to issues. """ + messages = { + "form_id_missing_enctype": _( + 'Form with id "{form_id}" contains file input, but does not have the attribute enctype="multipart/form-data".' + ), + "form_missing_enctype": _( + 'Form contains file input, but does not have the attribute enctype="multipart/form-data".' + ), + "input_refs_form_missing_enctype": _( + 'Input element references form with id "{form_id}", but the form does not have the attribute enctype="multipart/form-data".' + ), + } + title = _("Alerts") template = "debug_toolbar/panels/alerts.html" @@ -101,11 +113,12 @@ def check_invalid_file_form_configuration(self, html_content): for elem in form["submit_element_attrs"] ) ): - form_id = form["form_attrs"].get("id", "no form id") - alert = ( - f'Form with id "{form_id}" contains file input but ' - "does not have multipart/form-data encoding." - ) + if form_id := form["form_attrs"].get("id"): + alert = self.messages["form_id_missing_enctype"].format( + form_id=form_id + ) + else: + alert = self.messages["form_missing_enctype"] self.add_alert({"alert": alert}) # Check for file inputs that reference a form @@ -118,9 +131,8 @@ def check_invalid_file_form_configuration(self, html_content): if form_id and attrs.get("type") == "file": form_attrs = form_attrs_by_id.get(form_id) if form_attrs and form_attrs.get("enctype") != "multipart/form-data": - alert = ( - f'Input element references form with id "{form_id}" ' - "but the form does not have multipart/form-data encoding." + alert = self.messages["input_refs_form_missing_enctype"].format( + form_id=form_id ) self.add_alert({"alert": alert}) diff --git a/debug_toolbar/templates/debug_toolbar/panels/alerts.html b/debug_toolbar/templates/debug_toolbar/panels/alerts.html index b78d3d521..df208836d 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/alerts.html +++ b/debug_toolbar/templates/debug_toolbar/panels/alerts.html @@ -1,12 +1,12 @@ {% load i18n %} {% if alerts %} -

{% trans "alerts found" %}

+

{% trans "Alerts found" %}

{% for alert in alerts %}
  • {{ alert.alert }}
{% endfor %} {% else %} -

No alerts found.

+

{% trans "No alerts found" %}

{% endif %} diff --git a/tests/panels/test_alerts.py b/tests/panels/test_alerts.py index 43e9b7328..e61c8da12 100644 --- a/tests/panels/test_alerts.py +++ b/tests/panels/test_alerts.py @@ -26,8 +26,24 @@ def test_file_form_without_enctype_multipart_form_data(self): test_form = '
' result = self.panel.check_invalid_file_form_configuration(test_form) expected_error = ( - 'Form with id "test-form" contains file input ' - "but does not have multipart/form-data encoding." + 'Form with id "test-form" contains file input, ' + 'but does not have the attribute enctype="multipart/form-data".' + ) + self.assertEqual(result[0]["alert"], expected_error) + self.assertEqual(len(result), 1) + + def test_file_form_no_id_without_enctype_multipart_form_data(self): + """ + Test that the panel displays a form invalid message when there is + a file input but encoding not set to multipart/form-data. + + This should use the message when the form has no id. + """ + test_form = '
' + result = self.panel.check_invalid_file_form_configuration(test_form) + expected_error = ( + "Form contains file input, but does not have " + 'the attribute enctype="multipart/form-data".' ) self.assertEqual(result[0]["alert"], expected_error) self.assertEqual(len(result), 1) @@ -55,8 +71,8 @@ def test_referenced_file_input_without_enctype_multipart_form_data(self): result = self.panel.check_invalid_file_form_configuration(test_file_input) expected_error = ( - 'Input element references form with id "test-form" ' - "but the form does not have multipart/form-data encoding." + 'Input element references form with id "test-form", ' + 'but the form does not have the attribute enctype="multipart/form-data".' ) self.assertEqual(result[0]["alert"], expected_error) self.assertEqual(len(result), 1) @@ -79,7 +95,7 @@ def test_integration_file_form_without_enctype_multipart_form_data(self): self.assertIn("1 alert", self.panel.nav_subtitle) self.assertIn( - "Form with id "test-form" contains file input " - "but does not have multipart/form-data encoding.", + "Form with id "test-form" contains file input, " + "but does not have the attribute enctype="multipart/form-data".", self.panel.content, ) From 11872eb5d34d9f285db1b392889cf1b4c517bfde Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Wed, 3 Jul 2024 11:53:56 -0500 Subject: [PATCH 6/8] Expose a page in the example app that triggers the alerts panel. --- example/templates/bad_form.html | 14 ++++++++++++++ example/templates/index.html | 1 + example/urls.py | 5 +++++ 3 files changed, 20 insertions(+) create mode 100644 example/templates/bad_form.html diff --git a/example/templates/bad_form.html b/example/templates/bad_form.html new file mode 100644 index 000000000..f50662c6e --- /dev/null +++ b/example/templates/bad_form.html @@ -0,0 +1,14 @@ +{% load cache %} + + + + + Bad form + + +

Bad form test

+
+ +
+ + diff --git a/example/templates/index.html b/example/templates/index.html index ee00d5f05..527f5d2a3 100644 --- a/example/templates/index.html +++ b/example/templates/index.html @@ -14,6 +14,7 @@

Index of Tests

  • Prototype 1.7.3.0
  • Hotwire Turbo
  • htmx
  • +
  • Bad form
  • Django Admin

    {% endcache %} diff --git a/example/urls.py b/example/urls.py index 7569a57f9..535b82109 100644 --- a/example/urls.py +++ b/example/urls.py @@ -7,6 +7,11 @@ urlpatterns = [ path("", TemplateView.as_view(template_name="index.html"), name="home"), + path( + "bad-form/", + TemplateView.as_view(template_name="bad_form.html"), + name="bad_form", + ), path("jquery/", TemplateView.as_view(template_name="jquery/index.html")), path("mootools/", TemplateView.as_view(template_name="mootools/index.html")), path("prototype/", TemplateView.as_view(template_name="prototype/index.html")), From e8dd720b978734641f1fcb58e428e48ddcd08610 Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Wed, 3 Jul 2024 11:55:06 -0500 Subject: [PATCH 7/8] Move the alerts panel below the more used panels. --- debug_toolbar/settings.py | 2 +- docs/configuration.rst | 2 +- tests/panels/test_history.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py index 0fb3f81c5..48483cf40 100644 --- a/debug_toolbar/settings.py +++ b/debug_toolbar/settings.py @@ -58,7 +58,6 @@ def get_config(): PANELS_DEFAULTS = [ - "debug_toolbar.panels.alerts.AlertsPanel", "debug_toolbar.panels.history.HistoryPanel", "debug_toolbar.panels.versions.VersionsPanel", "debug_toolbar.panels.timer.TimerPanel", @@ -68,6 +67,7 @@ def get_config(): "debug_toolbar.panels.sql.SQLPanel", "debug_toolbar.panels.staticfiles.StaticFilesPanel", "debug_toolbar.panels.templates.TemplatesPanel", + "debug_toolbar.panels.alerts.AlertsPanel", "debug_toolbar.panels.cache.CachePanel", "debug_toolbar.panels.signals.SignalsPanel", "debug_toolbar.panels.redirects.RedirectsPanel", diff --git a/docs/configuration.rst b/docs/configuration.rst index 1ae9c05a8..42f90178a 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -20,7 +20,6 @@ included in the toolbar. It works like Django's ``MIDDLEWARE`` setting. The default value is:: DEBUG_TOOLBAR_PANELS = [ - 'debug_toolbar.panels.alerts.AlertsPanel', 'debug_toolbar.panels.history.HistoryPanel', 'debug_toolbar.panels.versions.VersionsPanel', 'debug_toolbar.panels.timer.TimerPanel', @@ -30,6 +29,7 @@ default value is:: 'debug_toolbar.panels.sql.SQLPanel', 'debug_toolbar.panels.staticfiles.StaticFilesPanel', 'debug_toolbar.panels.templates.TemplatesPanel', + 'debug_toolbar.panels.alerts.AlertsPanel', 'debug_toolbar.panels.cache.CachePanel', 'debug_toolbar.panels.signals.SignalsPanel', 'debug_toolbar.panels.redirects.RedirectsPanel', diff --git a/tests/panels/test_history.py b/tests/panels/test_history.py index 43e80c077..4c5244934 100644 --- a/tests/panels/test_history.py +++ b/tests/panels/test_history.py @@ -67,7 +67,6 @@ def test_urls(self): @override_settings(DEBUG=True) class HistoryViewsTestCase(IntegrationTestCase): PANEL_KEYS = { - "AlertsPanel", "VersionsPanel", "TimerPanel", "SettingsPanel", @@ -76,6 +75,7 @@ class HistoryViewsTestCase(IntegrationTestCase): "SQLPanel", "StaticFilesPanel", "TemplatesPanel", + "AlertsPanel", "CachePanel", "SignalsPanel", "ProfilingPanel", From 28e15a7124b7a0929d6fa6e5db4165249d8c195d Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Wed, 3 Jul 2024 11:55:57 -0500 Subject: [PATCH 8/8] Missed a period. --- docs/panels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/panels.rst b/docs/panels.rst index 41d82b370..c9ea6bbf0 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -18,7 +18,7 @@ This panel shows alerts for a set of pre-defined cases: - Alerts when the response has a form without the ``enctype="multipart/form-data"`` attribute and the form contains - a file input + a file input. History ~~~~~~~