Using Template Tags

Template tags are one of the most flexible extension points in SmallBlock CMS. They allow you to embed dynamic data directly into your templates, enabling you to mix Python logic with presentation without modifying the CMS core.

In this tutorial, you’ll learn how to define custom template tags, pass parameters, return complex data structures, and optionally render partial templates.

Before You Begin

Make sure you have:

  • A working SmallBlock CMS site from Build Your First Site.

  • Completed the Create a Plugin tutorial.

  • Basic familiarity with Python functions and modules.

  • Access to your project’s plugin directory.

How Template Tags Work

Template tags are Python functions decorated with @app.template_tag(name). They are loaded at application startup and made globally available inside your template engine.

A template tag can:

  • return a string

  • return a list, dict, or other iterable

  • render a partial template using app.render_template()

The following diagram shows the rendering flow:

digraph G {
    rankdir=LR;
    node [shape=box, style="rounded,filled", fillcolor="#eef3f8"];

    A [label="Template Tag Function\n(plugin.py)"];
    B [label="@app.template_tag(name)"];
    C [label="Template Engine"];
    D [label="Rendered Output"];

    A -> B -> C -> D;
}

Step 1 — Create a New Plugin (If Needed)

If you don’t already have a plugin for experimenting with tags, create one:

cd mysite/plugins
mkdir -p current_time
cd current_time
touch __init__.py plugin.py

Your folder now contains:

current_time/
├── __init__.py
└── plugin.py

Step 2 — Create a Basic Template Tag

Open plugin.py and add:

from datetime import datetime

def register(app):
    @app.template_tag("current_time")
    def current_time(format="%Y-%m-%d %H:%M:%S"):
        """Return the current server time, formatted."""
        return datetime.now().strftime(format)

    app.logger.info("Template tag 'current_time' registered.")

This creates a tag named current_time that accepts an optional format string, defaulting to ISO-like output.

Verify

Run:

python3 -c "from plugins.current_time.plugin import current_time; print(current_time())"

Step 3 — Use the Tag in a Template

Open any template (for example, templates/base.html) and insert:

<footer>
    <p>Server time: {% current_time "%H:%M:%S" %}</p>
</footer>

Reload your site — the current time should appear on every page render.

Step 4 — Build a Tag That Returns a List

Template tags can return lists that templates iterate over.

Extend plugin.py with:

def register(app):
    @app.template_tag("recent_pages")
    def recent_pages(limit=5):
        """Return the N most recently published pages."""
        pages = (
            app.models.Page.query
            .order_by(app.models.Page.published_at.desc())
            .limit(int(limit))
            .all()
        )
        return pages

Then add to a template:

<aside>
    <h3>Recent Pages</h3>
    <ul>
        {% for page in recent_pages 5 %}
            <li><a href="{{ page.url }}">{{ page.title }}</a></li>
        {% endfor %}
    </ul>
</aside>

The sidebar will update automatically as new content is published.

Step 5 — Create a Tag That Renders a Partial Template

For more complex markup, tags can render subtemplates.

Add to plugin.py:

def register(app):
    @app.template_tag("site_header")
    def site_header():
        """Render a custom header partial."""
        return app.render_template("partials/site_header.html")

Create templates/partials/site_header.html:

<header class="site-header">
    <h1>{{ site_name }}</h1>
    <nav>
        <a href="/">Home</a>
        <a href="/about/">About</a>
    </nav>
</header>

Include the tag anywhere in your layout:

{% site_header %}

Step 6 — Style the Output

For example, in static/css/custom.css:

.site-header {
    background-color: #0f1c2c;
    color: #e6edf3;
    padding: 1em;
    border-bottom: 2px solid #23445a;
}

.site-header a {
    color: #9baec8;
    text-decoration: none;
    margin-right: 1em;
}

.site-header a:hover {
    color: #e6edf3;
}

Troubleshooting

Tag doesn’t appear or raises an error

  • Ensure the tag name matches the decorator exactly.

  • Restart the development server — tags load at startup.

  • Confirm the plugin is enabled in your configuration:

    [plugins]
    enabled =
        current_time
    
  • Check logs:

    smallblock logs
    

Partial template not rendering

  • Ensure the path (e.g., partials/site_header.html) exists.

  • Confirm render_template() is being passed correct parameters.

Next Steps

Continue extending your templates and site design with: