DRY with Jinja Templates

DRY with Jinja Templates

Jinja is a great templating language that's used with Python. One of the easiest ways to not repeat yourself in Jinja is to use macros.

Let's say you want to build a blog.  You may want a blog that makes HTML like this:

<h1>My Blog</h1>
<h2>Featured Post</h2>
<h3>Why Ponies are Awesome</h3>
<p>
    Ponies are awesome because...
</p>
<h2>Other Posts</h2>
<h3>Where Is My Kitten</h3>
<p>
    Here he is!
</p>
<h3>All the cupcakes</h3>
<p>
    I ate all the cupcakes at Pinterest today.
</p>
A featured post and two other posts.

To simplify this, you might try to use for loops and variables in Jinja:

<h1>My Blog</h1>
<h2>Featured Post</h2>
<h3>{{ featured_post.title }}</h3>
{{ featured_post.body }}

{% for post in posts %}
    <h3>{{ post.title }}</h3>
    {{ post.body }}
{% endfor %}

It's only mildly repetititive.  Let's now add a date:

{% macro show_post(post) %}
    <h3>{{ post.title }}</h3>
    <span class="date">{{ post.date }}</span>
    {{ post.body }}
{% endmacro %}

<h1>My Blog</h1>
<h2>Featured Post</h2>
{{ show_post(featured_post) }}
{% for post in posts %}
    {{ show_post(post) }}
{% endfor %}
Add a date.

Adding a date is a bit more tedious.  In fact, any change to the snippet of what we want to see in a blog is going to be repetitive.  This is where a macro is handy:

{% macro show_post(post) %}
    <h3>{{ post.title }}</h3>
    <span class="date">{{ post.date }}</span>
    {{ post.body }}
{% endmacro %}

If I decide I don't want dates, or I want to change some tags, I can just change the macro.  Now my code looks like this:

{% macro show_post(post) %}
    <h3>{{ post.title }}</h3>
    <span class="date">{{ post.date }}</span>
    {{ post.body }}
{% endmacro %}

<h1>My Blog</h1>
<h2>Featured Post</h2>
{{ show_post(featured_post) }}
{% for post in posts %}
    {{ show_post(post) }}
{% endfor %}

That's a lot easier.  You can think of macros in templates the way you think of functions or methods in your backend code.

For a real world example, you can look at a commit to Amy Lam's Hackbright project.