From 9c7c84c40b3372f938062209f4acc172e0c32849 Mon Sep 17 00:00:00 2001 From: Tibor Leupold Date: Sun, 13 Aug 2023 20:26:12 -0700 Subject: [PATCH] Replace the custom template tag with a decorator The decorator now adds a method to the dataclass that handles the rendering logic. This is only done when no rendering method exists yet. This allows for completely custom rendering logic to be added. I find, this also reduces the logic and the complexity of the "templex" pattern, because we can work with fewer moving pieces. --- lpld/settings.py | 1 - lpld/templates/molecules/teaser/teaser.py | 45 +++++++++++++++++++++-- lpld/templates/pages/home/home.html | 5 +-- lpld/templatetags/templex.py | 11 ------ 4 files changed, 43 insertions(+), 19 deletions(-) delete mode 100644 lpld/templatetags/templex.py diff --git a/lpld/settings.py b/lpld/settings.py index 9fd773c2..b4e9c64b 100644 --- a/lpld/settings.py +++ b/lpld/settings.py @@ -134,7 +134,6 @@ "libraries": { "lpldutils": "lpld.templatetags.lpldutils", "navigation": "lpld.templatetags.navigation", - "templex": "lpld.templatetags.templex", }, }, }, diff --git a/lpld/templates/molecules/teaser/teaser.py b/lpld/templates/molecules/teaser/teaser.py index 20a86dda..be9481e4 100644 --- a/lpld/templates/molecules/teaser/teaser.py +++ b/lpld/templates/molecules/teaser/teaser.py @@ -1,14 +1,51 @@ import dataclasses -from typing import Optional +import functools +from typing import Optional, Type +from django import template as django_template from wagtail.images import models as images_models from wagtailmedia import models as media_models -@dataclasses.dataclass -class Teaser: - template = "molecules/teaser/teaser.html" +def templex(template: str): + """ + Turn class into a templex object. + + The class is turned into a data class and a `render` method is added (if it + doesn't already exist). Pass the template to render the templex with as a parameter + to the decorator. + + """ + + def wrapper(klass): + """ + The actual decorator. + + The template that this decorator adds to the class is injected from the + surrounding scope. + + """ + def render_templex(self): + templex_template = django_template.loader.get_template(self.template) + data_dict = dataclasses.asdict(self) + return templex_template.render(data_dict) + @functools.wraps(klass) + def wrap(klass: Type): + klass = dataclasses.dataclass(klass) + if not hasattr(klass, "template"): + klass.template = template + if not hasattr(klass, "render"): + klass.render = render_templex + return klass + + return wrap(klass) + + return wrapper + + +@templex(template="molecules/teaser/teaser.html") +class Teaser: heading: str introduction: str href: str diff --git a/lpld/templates/pages/home/home.html b/lpld/templates/pages/home/home.html index ef3c09b7..87638ae7 100644 --- a/lpld/templates/pages/home/home.html +++ b/lpld/templates/pages/home/home.html @@ -1,6 +1,5 @@ {% extends "base-page.html" %} -{% load templex %} -{% load slippers static templex wagtailcore_tags wagtailimages_tags %} +{% load slippers static wagtailcore_tags wagtailimages_tags %} {% block content %}
@@ -47,7 +46,7 @@ diff --git a/lpld/templatetags/templex.py b/lpld/templatetags/templex.py deleted file mode 100644 index 1b7fc282..00000000 --- a/lpld/templatetags/templex.py +++ /dev/null @@ -1,11 +0,0 @@ -import dataclasses - -from django import template - -register = template.Library() - - -@register.simple_tag(takes_context=False) -def include_templex(templex): - templex_template = template.loader.get_template(templex.template) - return templex_template.render(dataclasses.asdict(templex))