Skip to content

Commit

Permalink
Create decorator to use TOOLBAR_LANGUAGE in toolbar specific views.
Browse files Browse the repository at this point in the history
This reviews the third-party panel documentation to reference
these two decorators and explain them. They aren't necessary
but should be used.
  • Loading branch information
tim-schilling committed Dec 7, 2022
1 parent b41da3c commit d38ff8f
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 20 deletions.
16 changes: 16 additions & 0 deletions debug_toolbar/decorators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import functools

from django.http import Http404
from django.utils.translation import get_language, override as language_override

from debug_toolbar import settings as dt_settings


def require_show_toolbar(view):
Expand All @@ -15,3 +18,16 @@ def inner(request, *args, **kwargs):
return view(request, *args, **kwargs)

return inner


def render_with_toolbar_language(view):
"""Force any rendering within the view to use the toolbar's language."""

@functools.wraps(view)
def inner(request, *args, **kwargs):

lang = dt_settings.get_config()["TOOLBAR_LANGUAGE"] or get_language()
with language_override(lang):
return view(request, *args, **kwargs)

return inner
4 changes: 3 additions & 1 deletion debug_toolbar/panels/history/views.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from django.http import HttpResponseBadRequest, JsonResponse
from django.template.loader import render_to_string

from debug_toolbar.decorators import require_show_toolbar
from debug_toolbar.decorators import render_with_toolbar_language, require_show_toolbar
from debug_toolbar.panels.history.forms import HistoryStoreForm
from debug_toolbar.toolbar import DebugToolbar


@require_show_toolbar
@render_with_toolbar_language
def history_sidebar(request):
"""Returns the selected debug toolbar history snapshot."""
form = HistoryStoreForm(request.GET)
Expand Down Expand Up @@ -37,6 +38,7 @@ def history_sidebar(request):


@require_show_toolbar
@render_with_toolbar_language
def history_refresh(request):
"""Returns the refreshed list of table rows for the History Panel."""
form = HistoryStoreForm(request.GET)
Expand Down
5 changes: 4 additions & 1 deletion debug_toolbar/panels/sql/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt

from debug_toolbar.decorators import require_show_toolbar
from debug_toolbar.decorators import render_with_toolbar_language, require_show_toolbar
from debug_toolbar.forms import SignedDataForm
from debug_toolbar.panels.sql.forms import SQLSelectForm

Expand All @@ -18,6 +18,7 @@ def get_signed_data(request):

@csrf_exempt
@require_show_toolbar
@render_with_toolbar_language
def sql_select(request):
"""Returns the output of the SQL SELECT statement"""
verified_data = get_signed_data(request)
Expand Down Expand Up @@ -47,6 +48,7 @@ def sql_select(request):

@csrf_exempt
@require_show_toolbar
@render_with_toolbar_language
def sql_explain(request):
"""Returns the output of the SQL EXPLAIN on the given query"""
verified_data = get_signed_data(request)
Expand Down Expand Up @@ -85,6 +87,7 @@ def sql_explain(request):

@csrf_exempt
@require_show_toolbar
@render_with_toolbar_language
def sql_profile(request):
"""Returns the output of running the SQL and getting the profiling statistics"""
verified_data = get_signed_data(request)
Expand Down
3 changes: 2 additions & 1 deletion debug_toolbar/panels/templates/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
from django.template.loader import render_to_string
from django.utils.html import format_html, mark_safe

from debug_toolbar.decorators import require_show_toolbar
from debug_toolbar.decorators import render_with_toolbar_language, require_show_toolbar


@require_show_toolbar
@render_with_toolbar_language
def template_source(request):
"""
Return the source of a template, syntax-highlighted by Pygments if
Expand Down
17 changes: 6 additions & 11 deletions debug_toolbar/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
from django.http import JsonResponse
from django.utils.html import escape
from django.utils.translation import (
get_language,
gettext as _,
override as lang_override,
)
from django.utils.translation import gettext as _

from debug_toolbar.decorators import require_show_toolbar
from debug_toolbar.decorators import render_with_toolbar_language, require_show_toolbar
from debug_toolbar.toolbar import DebugToolbar


@require_show_toolbar
@render_with_toolbar_language
def render_panel(request):
"""Render the contents of a panel"""
toolbar = DebugToolbar.fetch(request.GET["store_id"])
Expand All @@ -22,9 +19,7 @@ def render_panel(request):
content = "<p>%s</p>" % escape(content)
scripts = []
else:
lang = toolbar.config["TOOLBAR_LANGUAGE"] or get_language()
with lang_override(lang):
panel = toolbar.get_panel_by_id(request.GET["panel_id"])
content = panel.content
scripts = panel.scripts
panel = toolbar.get_panel_by_id(request.GET["panel_id"])
content = panel.content
scripts = panel.scripts
return JsonResponse({"content": content, "scripts": scripts})
1 change: 1 addition & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Pending

* Use ``TOOLBAR_LANGUAGE`` setting when rendering individual panels
that are loaded via AJAX.
* Add decorator for rendering toolbar views with ``TOOLBAR_LANGUAGE``.

3.8.1 (2022-12-03)
------------------
Expand Down
6 changes: 3 additions & 3 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ Toolbar options
the request doesn't originate from the toolbar itself, EG that
``is_toolbar_request`` is false for a given request.

.. _TOOLBAR_LANGUAGE:

* ``TOOLBAR_LANGUAGE``

Default: ``None``
Expand All @@ -160,9 +162,7 @@ Toolbar options
render the toolbar in a different language than what the application is
rendered in. For example, if you wish to use English for development,
but want to render your application in French, you would set this to
``"en-us"`` and `settings.LANGUAGE_CODE`_ to ``"fr"``.

.. _settings.LANGUAGE_CODE: https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-LANGUAGE_CODE
``"en-us"`` and :setting:`LANGUAGE_CODE` to ``"fr"``.

Panel options
~~~~~~~~~~~~~
Expand Down
15 changes: 12 additions & 3 deletions docs/panels.rst
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,18 @@ Third-party panels must subclass :class:`~debug_toolbar.panels.Panel`,
according to the public API described below. Unless noted otherwise, all
methods are optional.

Panels can ship their own templates, static files and views. All views should
be decorated with ``debug_toolbar.decorators.require_show_toolbar`` to prevent
unauthorized access. There is no public CSS API at this time.
Panels can ship their own templates, static files and views.

Any views defined for the third-party panel use the following decorators:

- ``debug_toolbar.decorators.require_show_toolbar`` - Prevents unauthorized
access to the view.
- ``debug_toolbar.decorators.render_with_toolbar_language`` - Supports
internationalization for any content rendered by the view. This will render
the response with the :ref:`TOOLBAR_LANGUAGE <TOOLBAR_LANGUAGE>` rather than
:setting:`LANGUAGE_CODE`.

There is no public CSS API at this time.

.. autoclass:: debug_toolbar.panels.Panel

Expand Down
26 changes: 26 additions & 0 deletions tests/test_decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from unittest.mock import patch

from django.http import HttpResponse
from django.test import RequestFactory, TestCase
from django.test.utils import override_settings

from debug_toolbar.decorators import render_with_toolbar_language


@render_with_toolbar_language
def stub_view(request):
return HttpResponse(200)


@override_settings(DEBUG=True, LANGUAGE_CODE="fr")
class RenderWithToolbarLanguageTestCase(TestCase):
@override_settings(DEBUG_TOOLBAR_CONFIG={"TOOLBAR_LANGUAGE": "de"})
@patch("debug_toolbar.decorators.language_override")
def test_uses_toolbar_language(self, mock_language_override):
stub_view(RequestFactory().get("/"))
mock_language_override.assert_called_once_with("de")

@patch("debug_toolbar.decorators.language_override")
def test_defaults_to_django_language_code(self, mock_language_override):
stub_view(RequestFactory().get("/"))
mock_language_override.assert_called_once_with("fr")

0 comments on commit d38ff8f

Please sign in to comment.