Lately I’ve been writing more Django template tags than usual and last Thursday morning, I spotted a Mastodon Thread about Django templates and composability.
This sent me down a bit of a rabbit hole and I wrote a proof-of-concept library for writing class-based templatetags. It provides developpers with all the tools used by simple_tag and inclusion_tag so one doesn’t have to rewrite things like token parsing every time they need to write an advanced template tag, and more.
The docs and blog post would be easier to understand with usage examples for the various tags, like how the simple “hello” tag can be used as {% hello %} (I think?).
I am not sure I like the “one base class” approach. Inheriting from TemplateTag and switching between simple/inclusion/block tags by changing which methods/attributes you implement seems a bit harder to operate than having different base classes. It also makes them hard to type check or otherwise verify. For example, if I misspell template_name for an inclusion tag, afaik that will revert the tag to being a simple tag, causing an error due to render() returning the wrong type.
Overall, great experiment. I will keep it in mind for when I’m next writing some tags.
Maybe a next step would be to see if a class-based approach could simplify any of the tags within Django?
looks like Django 5.2 should have simple_block_tag
Yes, Jake told me about it. I’m glad it’s going to be in 5.2.
But it doesn’t really help with the complexity underlying those Library methods that all look very similar. It also only helps a subset of people trying to build more complex tags.
The docs and blog post would be easier to understand with usage examples for the various tags, like how the simple “hello” tag can be used as {% hello %}
Good point, I’ll add those.
I am not sure I like the “one base class” approach
I’m not sure that’s a requirement either… I can see the point about type checking. And I don’t see any reason not to have a set of specialized classes that inherit from TemplateTag and set some constaints, like setting a node_class attribute to override the property of the same name.
I know that one of the major complaints about class-based views is the lasagna architecture of mixins, so I’d still rather have that TemplateTag class as a “complete” base and restrict the behaviour in subclasses rather than the other way around.
Maybe a next step would be to see if a class-based approach could simplify any of the tags within Django?
What do you suggest as the way to do that? A diff?
A full on monkey-patch in the same library that would ensure backwards compatibility but uses cbtt for everything (including the incoming simple_block_tag and block_inclusion_tag: yak/utils.py · main · Emma / Django YAK · GitLab
Note that tags like if and for would not be possible to port tight now as yak would need some sort of “else_nodelist(s)” , which is a thing I’ve poundered but not implemented at this stage.
Also, if you’re going where I think you’re going (this not being just a library but a replacement for the current templatetags) I don’t think all existing tags need to be re-written
I debated about using something more meaningful but then everyone who’s used to digging in would be confused. I reasoned that using custom arbitrary strings (ie notas or with) is in the realm of “advanced” usage and therefore kept the term most “advanced templataggers” would already be familiar with