From ecd8b7b5e508c0d8adf8607f2549040b10dfaded Mon Sep 17 00:00:00 2001 From: Dan Jacob Date: Wed, 12 May 2021 12:43:24 +0300 Subject: [PATCH] Using format_html --- doc/source/main.rst | 4 +- .../jinja2/turbo_response/turbo_frame.html | 1 - .../jinja2/turbo_response/turbo_stream.html | 1 - src/turbo_response/mixins.py | 15 +-- src/turbo_response/renderers.py | 114 ++---------------- src/turbo_response/response.py | 20 ++- src/turbo_response/template.py | 8 +- .../templates/turbo_response/turbo_frame.html | 1 - .../turbo_response/turbo_stream.html | 1 - tests/test_frame.py | 44 ------- tests/test_renderers.py | 72 ----------- tests/test_stream.py | 37 ------ tests/test_views.py | 35 ------ 13 files changed, 23 insertions(+), 330 deletions(-) delete mode 100644 src/turbo_response/jinja2/turbo_response/turbo_frame.html delete mode 100644 src/turbo_response/jinja2/turbo_response/turbo_stream.html delete mode 100644 src/turbo_response/templates/turbo_response/turbo_frame.html delete mode 100644 src/turbo_response/templates/turbo_response/turbo_stream.html diff --git a/doc/source/main.rst b/doc/source/main.rst index f953084..fd792d6 100644 --- a/doc/source/main.rst +++ b/doc/source/main.rst @@ -32,9 +32,7 @@ Next update **INSTALLED_APPS**: ... ] -The turbo stream and frame rendering uses **turbo_response.renderers.DjangoTemplates** by default. If you want to change this default import string with the Django setting **TURBO_RESPONSE_RENDERER**. For example, if you want to render all templates through Jinja2 you can use **turbo_response.renderers.Jinja2**. In almost all cases however there is probably no need to change the default settings. - -**Note**: This install does not include any client libraries (Turbo or Stimulus). You may wish to add these yourself using your preferred Javascript build tool, or use a CDN. Please refer to the Hotwire documentation on installing these libraries. +**Note**: This install does not include any client libraries (e.g. Turbo or Stimulus). You may wish to add these yourself using your preferred Javascript build tool, or use a CDN. Please refer to the Hotwire documentation on installing these libraries. ========== diff --git a/src/turbo_response/jinja2/turbo_response/turbo_frame.html b/src/turbo_response/jinja2/turbo_response/turbo_frame.html deleted file mode 100644 index d6a6757..0000000 --- a/src/turbo_response/jinja2/turbo_response/turbo_frame.html +++ /dev/null @@ -1 +0,0 @@ -{{ content }} diff --git a/src/turbo_response/jinja2/turbo_response/turbo_stream.html b/src/turbo_response/jinja2/turbo_response/turbo_stream.html deleted file mode 100644 index 5095dd7..0000000 --- a/src/turbo_response/jinja2/turbo_response/turbo_stream.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/turbo_response/mixins.py b/src/turbo_response/mixins.py index 4420eea..1eb7ca2 100644 --- a/src/turbo_response/mixins.py +++ b/src/turbo_response/mixins.py @@ -10,7 +10,6 @@ from .constants import Action from .frame import TurboFrame -from .renderers import BaseRenderer from .response import HttpResponseSeeOther from .stream import TurboStream, TurboStreamAction @@ -19,9 +18,6 @@ class TurboStreamMixin: turbo_stream_action: Optional[Action] = None turbo_stream_target: Optional[str] = None - def get_turbo_stream_renderer(self) -> Optional[BaseRenderer]: - return None - def get_turbo_stream(self) -> TurboStreamAction: target = self.get_turbo_stream_target() @@ -58,9 +54,6 @@ def get_turbo_stream_target(self) -> Optional[str]: class TurboFrameMixin: turbo_frame_dom_id: Optional[str] = None - def get_turbo_frame_renderer(self) -> Optional[BaseRenderer]: - return None - def get_turbo_frame(self) -> TurboFrame: dom_id = self.get_turbo_frame_dom_id() if not dom_id: @@ -94,7 +87,6 @@ def render_turbo_stream(self, **kwargs) -> HttpResponse: return self.get_turbo_stream().response( self.get_response_content(), is_safe=self.is_turbo_stream_content_safe(), - renderer=self.get_turbo_stream_renderer(), **kwargs, ) @@ -115,7 +107,7 @@ def render_turbo_stream(self, context: Dict[str, Any], **kwargs) -> HttpResponse return ( self.get_turbo_stream() .template(self.get_template_names(), context, using=self.template_engine) - .response(self.request, renderer=self.get_turbo_stream_renderer(), **kwargs) + .response(self.request, **kwargs) ) @@ -230,7 +222,7 @@ def render_turbo_stream_response(self, **context) -> HttpResponse: context=self.get_context_data(**context), using=self.template_engine, ) - .response(self.request, renderer=self.get_turbo_stream_renderer()) + .response(self.request) ) def form_invalid(self, form: forms.Form) -> HttpResponse: @@ -276,7 +268,6 @@ def render_turbo_frame(self, **kwargs) -> HttpResponse: return self.get_turbo_frame().response( self.get_response_content(), is_safe=self.is_turbo_frame_content_safe(), - renderer=self.get_turbo_frame_renderer(), **kwargs, ) @@ -296,5 +287,5 @@ def render_turbo_frame(self, context: Dict[str, Any], **kwargs) -> HttpResponse: return ( self.get_turbo_frame() .template(self.get_template_names(), context, using=self.template_engine) - .response(self.request, renderer=self.get_turbo_frame_renderer(), **kwargs) + .response(self.request, **kwargs) ) diff --git a/src/turbo_response/renderers.py b/src/turbo_response/renderers.py index 44fca71..73ab5ff 100644 --- a/src/turbo_response/renderers.py +++ b/src/turbo_response/renderers.py @@ -1,36 +1,14 @@ -import pathlib -from functools import lru_cache -from typing import Dict, Optional - -from django.template import Template -from django.template.backends.django import DjangoTemplates as DjangoTemplatesBackend -from django.template.engine import Engine -from django.template.loader import get_template -from django.utils.functional import cached_property -from django.utils.module_loading import import_string +from django.utils.html import format_html from django.utils.safestring import mark_safe from .constants import Action -class BaseRenderer: - """This classes is based on django form widget renderer: we can determine - the template engine used to render the wrapper templates in settings or per instance.""" - - def get_template(self, template_name: str) -> Template: - raise NotImplementedError("subclasses must implement get_template()") - - def render(self, template_name: str, context: Dict) -> str: - template = self.get_template(template_name) - return template.render(context).strip() - - def render_turbo_stream( action: Action, target: str, content: str = "", is_safe: bool = False, - renderer: Optional[BaseRenderer] = None, ) -> str: """Wraps content in correct tags. @@ -38,16 +16,19 @@ def render_turbo_stream( :param target: the DOM ID target of the stream :param content: content to be wrapped. Can be empty. :param is_safe: mark content safe for HTML escaping. - :param renderer: template renderer class :return: ** string """ - return render( - "turbo_response/turbo_stream.html", + + if is_safe: + content = mark_safe(content) + + return format_html( + '' + "", + action.value, + target, content, - is_safe, - renderer, - extra_context={"action": action.value, "target": target}, ) @@ -55,7 +36,6 @@ def render_turbo_frame( dom_id: str, content: str = "", is_safe: bool = False, - renderer: Optional[BaseRenderer] = None, ) -> str: """ @@ -64,82 +44,10 @@ def render_turbo_frame( :param dom_id: a DOM ID present in the content :param content: content of the turbo-frame :param is_safe: mark content safe for HTML escaping. - :param renderer: template renderer class :return: ** string """ - return render( - "turbo_response/turbo_frame.html", - content, - is_safe, - renderer, - extra_context={"dom_id": dom_id}, - ) - - -@lru_cache() -def get_default_renderer() -> BaseRenderer: - """Get the default renderer class. - - :return: renderer subclass: default DjangoTemplates - - """ - from django.conf import settings - - renderer_class_name = getattr( - settings, "TURBO_RESPONSE_RENDERER", "turbo_response.renderers.DjangoTemplates" - ) - - renderer_class = import_string(renderer_class_name) - return renderer_class() - - -def render( - template_name: str, - content: str, - is_safe: bool, - renderer: Optional[BaseRenderer] = None, - extra_context: Optional[Dict] = None, -) -> str: - - renderer = renderer or get_default_renderer() - if is_safe: content = mark_safe(content) - return renderer.render(template_name, {"content": content, **(extra_context or {})}) - - -class EngineMixin: - backend: Engine - - def get_template(self, template_name: str) -> Template: - return self.engine.get_template(template_name) - - @cached_property - def engine(self) -> Engine: - return self.backend( - { - "APP_DIRS": True, - "DIRS": [pathlib.Path(__file__).parent / self.backend.app_dirname], - "NAME": "turbo_response", - "OPTIONS": {}, - } - ) - - -class DjangoTemplates(EngineMixin, BaseRenderer): - backend = DjangoTemplatesBackend - - -class Jinja2(EngineMixin, BaseRenderer): - @cached_property - def backend(self) -> Engine: - from django.template.backends.jinja2 import Jinja2 - - return Jinja2 - - -class TemplatesSetting(BaseRenderer): - def get_template(self, template_name: str) -> Template: - return get_template(template_name) + return format_html('{}', dom_id, content) diff --git a/src/turbo_response/response.py b/src/turbo_response/response.py index 4cbc76c..c05a1ba 100644 --- a/src/turbo_response/response.py +++ b/src/turbo_response/response.py @@ -10,7 +10,7 @@ from django.template.response import TemplateResponse from .constants import TURBO_STREAM_MIME_TYPE, Action -from .renderers import BaseRenderer, render_turbo_frame, render_turbo_stream +from .renderers import render_turbo_frame, render_turbo_stream class HttpResponseSeeOther(HttpResponseRedirect): @@ -66,13 +66,10 @@ def __init__( action: Optional[Action] = None, target: Optional[str] = None, is_safe: bool = False, - renderer: Optional[BaseRenderer] = None, **response_kwargs, ): if action and target and isinstance(content, str): - content = render_turbo_stream( - action, target, content, is_safe=is_safe, renderer=renderer - ) + content = render_turbo_stream(action, target, content, is_safe=is_safe) super().__init__(content, **response_kwargs) @@ -97,7 +94,6 @@ def __init__( *, action: Action, target: str, - renderer: Optional[BaseRenderer] = None, **kwargs, ): @@ -115,7 +111,6 @@ def __init__( self._target = target self._action = action - self._renderer = renderer @property def rendered_content(self) -> str: @@ -123,7 +118,6 @@ def rendered_content(self) -> str: action=self._action, target=self._target, content=super().rendered_content, - renderer=self._renderer, is_safe=True, ) @@ -137,11 +131,14 @@ def __init__( *, dom_id: str, is_safe: bool = False, - renderer: Optional[BaseRenderer] = None, **response_kwargs, ): super().__init__( - render_turbo_frame(dom_id, content, is_safe=is_safe, renderer=renderer), + render_turbo_frame( + dom_id, + content, + is_safe=is_safe, + ), **response_kwargs, ) @@ -165,7 +162,6 @@ def __init__( context: Optional[Mapping[str, Any]] = None, *, dom_id, - renderer: Optional[BaseRenderer] = None, **kwargs, ): @@ -177,7 +173,6 @@ def __init__( ) self._dom_id = dom_id - self._renderer = renderer @property def rendered_content(self) -> str: @@ -185,5 +180,4 @@ def rendered_content(self) -> str: self._dom_id, super().rendered_content, is_safe=True, - renderer=self._renderer, ) diff --git a/src/turbo_response/template.py b/src/turbo_response/template.py index c9054a6..ba0cec9 100644 --- a/src/turbo_response/template.py +++ b/src/turbo_response/template.py @@ -3,7 +3,7 @@ from django.template.loader import render_to_string from .constants import Action -from .renderers import BaseRenderer, render_turbo_frame, render_turbo_stream +from .renderers import render_turbo_frame, render_turbo_stream def render_turbo_stream_template( @@ -12,7 +12,6 @@ def render_turbo_stream_template( *, action: Action, target: str, - renderer: Optional[BaseRenderer] = None, **template_kwargs ) -> str: """Renders a ** template. @@ -21,7 +20,6 @@ def render_turbo_stream_template( :param context: template context :param action: turbo-stream action :param target: turbo-stream target - :param renderer: turbo-stream template renderer """ return render_turbo_stream( action, @@ -37,7 +35,6 @@ def render_turbo_stream_template( **template_kwargs, ).strip(), is_safe=True, - renderer=renderer, ) @@ -46,7 +43,6 @@ def render_turbo_frame_template( context: Optional[Dict[str, Any]] = None, *, dom_id: str, - renderer: Optional[BaseRenderer] = None, **kwargs ) -> str: """Renders a ** template. @@ -54,7 +50,6 @@ def render_turbo_frame_template( :param template: template name or names :param context: template context :param dom_id: turbo-frame DOM ID - :param renderer: turbo-frame template renderer """ return render_turbo_frame( @@ -69,5 +64,4 @@ def render_turbo_frame_template( **kwargs, ).strip(), is_safe=True, - renderer=renderer, ) diff --git a/src/turbo_response/templates/turbo_response/turbo_frame.html b/src/turbo_response/templates/turbo_response/turbo_frame.html deleted file mode 100644 index d6a6757..0000000 --- a/src/turbo_response/templates/turbo_response/turbo_frame.html +++ /dev/null @@ -1 +0,0 @@ -{{ content }} diff --git a/src/turbo_response/templates/turbo_response/turbo_stream.html b/src/turbo_response/templates/turbo_response/turbo_stream.html deleted file mode 100644 index 5095dd7..0000000 --- a/src/turbo_response/templates/turbo_response/turbo_stream.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/test_frame.py b/tests/test_frame.py index c4d61af..fb81a3c 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1,7 +1,6 @@ import http from turbo_response import TurboFrame -from turbo_response.renderers import Jinja2 class TestTurboFrame: @@ -9,10 +8,6 @@ def test_render(self): s = TurboFrame("my-form").render("OK") assert s == 'OK' - def test_render_jinja2(self): - s = TurboFrame("my-form").render("OK", renderer=Jinja2()) - assert s == 'OK' - def test_render_xss(self): s = TurboFrame("my-form").render("") assert ( @@ -32,27 +27,12 @@ def test_template(self): assert "my content" in s assert '' in s - def test_template_jinja2(self): - s = ( - TurboFrame("my-form") - .template("simple.html", {"msg": "my content"}) - .render(renderer=Jinja2()) - ) - assert "my content" in s - assert '' in s - def test_response(self): resp = TurboFrame("my-form").response("OK") assert resp.status_code == http.HTTPStatus.OK assert b"OK" in resp.content assert b'") assert resp.status_code == http.HTTPStatus.OK @@ -75,16 +55,6 @@ def test_template_render(self, rf): assert "my content" in s assert '' ) - def test_render_content_django_templates(self): - s = render_turbo_stream( - action=Action.REPLACE, - target="test", - content="my content", - renderer=DjangoTemplates(), - ) - assert ( - s - == '' - ) - - def test_render_content_jinja2(self): - s = render_turbo_stream( - action=Action.REPLACE, - target="test", - content="my content", - renderer=Jinja2(), - ) - assert ( - s - == '' - ) - def test_render_content_xss(self): s = render_turbo_stream( action=Action.REPLACE, @@ -56,18 +31,6 @@ def test_render_content_xss(self): == '' ) - def test_render_content_jinja2_xss(self): - s = render_turbo_stream( - action=Action.REPLACE, - target="test", - content="", - renderer=Jinja2(), - ) - assert ( - s - == '' - ) - def test_render_content_is_safe(self): s = render_turbo_stream( action=Action.REPLACE, @@ -80,19 +43,6 @@ def test_render_content_is_safe(self): == '' ) - def test_render_content_is_safe_jinja2(self): - s = render_turbo_stream( - action=Action.REPLACE, - target="test", - content="", - is_safe=True, - renderer=Jinja2(), - ) - assert ( - s - == '' - ) - class TestRenderTurboFrame: def test_render_empty_frame(self): @@ -106,12 +56,6 @@ def test_render_content(self): ) assert s == 'my content' - def test_render_content_django_templates(self): - s = render_turbo_frame( - dom_id="test", content="my content", renderer=DjangoTemplates() - ) - assert s == 'my content' - def test_render_xss(self): s = render_turbo_frame( dom_id="test", @@ -119,16 +63,6 @@ def test_render_xss(self): ) assert s == '<script></script>' - def test_render_xss_jinja2(self): - s = render_turbo_frame( - dom_id="test", content="", renderer=Jinja2() - ) - assert s == '<script></script>' - - def test_render_content_jinja2(self): - s = render_turbo_frame(dom_id="test", content="my content", renderer=Jinja2()) - assert s == 'my content' - def test_render_content_is_safe(self): s = render_turbo_frame( dom_id="test", @@ -136,9 +70,3 @@ def test_render_content_is_safe(self): is_safe=True, ) assert s == '' - - def test_render_content_is_safe_jinja2(self): - s = render_turbo_frame( - dom_id="test", content="", is_safe=True, renderer=Jinja2() - ) - assert s == '' diff --git a/tests/test_stream.py b/tests/test_stream.py index 37d3d84..9ee54ae 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -1,7 +1,6 @@ import http from turbo_response import TurboStream -from turbo_response.renderers import Jinja2 class TestTurboStream: @@ -12,13 +11,6 @@ def test_render(self): == '' ) - def test_render_jinja2(self): - s = TurboStream("my-form").append.render("OK", renderer=Jinja2()) - assert ( - s - == '' - ) - def test_render_xss(self): s = TurboStream("my-form").append.render("") assert ( @@ -42,15 +34,6 @@ def test_template(self): assert "my content" in s assert '' in s - def test_template_jinja2(self): - s = ( - TurboStream("my-form") - .append.template("simple.html", {"msg": "my content"}) - .render(renderer=Jinja2()) - ) - assert "my content" in s - assert '' in s - def test_template_xss(self): s = ( TurboStream("my-form") @@ -84,12 +67,6 @@ def test_response(self): assert b"OK" in resp.content assert b'") assert resp.status_code == http.HTTPStatus.OK @@ -129,17 +106,3 @@ def test_template_response(self, rf): content = resp.render().content assert b"
my content
" in content assert b'my content" in content - assert b'