Sneaking Metadata into Mako Templates
Bob Rubbens
Here’s a little trick I use to sneak some metadata into my Mako
templates.
You can define python methods as top-level definitions in a Mako
template. Then, from the python side, you access the module that
implements the template, and simply call the function directly.
Here’s an example:
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "mako",
# ]
# ///
from mako.template import Template
# Construct the template, containing `foo` as a top-level module definition.
template = Template("""
<%!
def foo():
return { "extension": ".html" };
%>
Hello world!
""")
# Access the module of the template, call `foo` directly.
print(template.module.foo())
# Let's render the template as well while we're at it.
print(template.render())
To test this, you can either install Mako locally, or you can run the
script with uv, which handles the dependencies implicitly. Serhii wrote
a concise blogpost explaining this functionality.
Executing the script prints the following:
❯ uv run --script test.py
{'extension': '.html'}
Hello world!
In the documentation of the Template class this module field is
mentioned implicitly, so I’m not sure if this is supposed to be a stable
feature of the Mako API. For my personal website this is fine.
While this is a powerful mechanism, I only use it to annotate my
templates with metadata (for now). E.g. what the output extension of the
file produced by the template should be, or if the template is supposed
to be reusable or produces one particular page, etc.
Because Mako is so flexible, I don’t just use it for templating-specific
stuff, but also as a way to do poor man’s literate programming in
Python. While it’s a bit messy, it’s also effective and gets the job
done.