From 95ab4227f55b56cec0d9c0c641139388636b5609 Mon Sep 17 00:00:00 2001 From: Matthieu <2222826+d9pouces@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:18:21 +0200 Subject: [PATCH 1/2] Avoid an exception with Django-channels If you apply Django middlewares on a HttpRequest without "wsgi.multiprocess" in META, an exception is raised by DJT. This simple patch avoids this bug. --- debug_toolbar/toolbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py index 40e758107..9a20500e1 100644 --- a/debug_toolbar/toolbar.py +++ b/debug_toolbar/toolbar.py @@ -97,7 +97,7 @@ def should_render_panels(self): """ render_panels = self.config["RENDER_PANELS"] if render_panels is None: - render_panels = self.request.META["wsgi.multiprocess"] + render_panels = self.request.META.get("wsgi.multiprocess", False) return render_panels # Handle storing toolbars in memory and fetching them later on From 75cabbe54b84c1da05cdd8dbe85392fef470b5ee Mon Sep 17 00:00:00 2001 From: tschilling Date: Mon, 15 May 2023 20:29:49 -0500 Subject: [PATCH 2/2] If wsgi.multiprocess isn't set, render panels on each request. The likely cause of this is that the application is using ASGI since wsgi.multiprocess is a required key for a WSGI application. Since the toolbar currently doesn't support async applications, it's pretty likely that it won't work for this request. If you're a developer reading this and you think I'm wrong, you can set the RENDER_PANELS setting to forcibly control this setting. --- debug_toolbar/toolbar.py | 10 +++++++--- docs/changes.rst | 6 ++++++ tests/test_integration.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py index 9a20500e1..31010f47f 100644 --- a/debug_toolbar/toolbar.py +++ b/debug_toolbar/toolbar.py @@ -95,9 +95,13 @@ def should_render_panels(self): If False, the panels will be loaded via Ajax. """ - render_panels = self.config["RENDER_PANELS"] - if render_panels is None: - render_panels = self.request.META.get("wsgi.multiprocess", False) + if (render_panels := self.config["RENDER_PANELS"]) is None: + # If wsgi.multiprocess isn't in the headers, then it's likely + # being served by ASGI. This type of set up is most likely + # incompatible with the toolbar until + # https://github.com/jazzband/django-debug-toolbar/issues/1430 + # is resolved. + render_panels = self.request.META.get("wsgi.multiprocess", True) return render_panels # Handle storing toolbars in memory and fetching them later on diff --git a/docs/changes.rst b/docs/changes.rst index 7c0338385..75b95c562 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -14,6 +14,12 @@ Pending presence of other code which also monkey patches those methods. * Update all timing code that used :py:func:`time.time()` to use :py:func:`time.perf_counter()` instead. +* Made the check on ``request.META["wsgi.multiprocess"]`` optional, but + defaults to forcing the toolbar to render the panels on each request. This + is because it's likely an ASGI application that's serving the responses + and that's more likely to be an incompatible setup. If you find that this + is incorrect for you in particular, you can use the ``RENDER_PANELS`` + setting to forcibly control this logic. 4.0.0 (2023-04-03) ------------------ diff --git a/tests/test_integration.py b/tests/test_integration.py index b292dcbf0..71340709a 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -65,6 +65,35 @@ def test_show_toolbar_INTERNAL_IPS(self): with self.settings(INTERNAL_IPS=[]): self.assertFalse(show_toolbar(self.request)) + def test_should_render_panels_RENDER_PANELS(self): + """ + The toolbar should force rendering panels on each request + based on the RENDER_PANELS setting. + """ + toolbar = DebugToolbar(self.request, self.get_response) + self.assertFalse(toolbar.should_render_panels()) + toolbar.config["RENDER_PANELS"] = True + self.assertTrue(toolbar.should_render_panels()) + toolbar.config["RENDER_PANELS"] = None + self.assertTrue(toolbar.should_render_panels()) + + def test_should_render_panels_multiprocess(self): + """ + The toolbar should render the panels on each request when wsgi.multiprocess + is True or missing. + """ + request = rf.get("/") + request.META["wsgi.multiprocess"] = True + toolbar = DebugToolbar(request, self.get_response) + toolbar.config["RENDER_PANELS"] = None + self.assertTrue(toolbar.should_render_panels()) + + request.META["wsgi.multiprocess"] = False + self.assertFalse(toolbar.should_render_panels()) + + request.META.pop("wsgi.multiprocess") + self.assertTrue(toolbar.should_render_panels()) + def _resolve_stats(self, path): # takes stats from Request panel self.request.path = path