The Django templating system that ActionKit leverages to let organizations build customized pages and mailings does provide an admirable amount of flexibility, but as those templates grow larger and more complicated we can ourselves wishing we had equivalents of some of the tools found in other programming languages, such as subroutines.
Conveniently, ActionKit provides us with a mechanism that will allow us to build template fragments and then call them when needed to complete our template.
Example
Let’s start with this simplified caricature of a donation mailing:
<p>Dear {{ user.first_name|default:"Friend"|title }},</p>
<p> Please make a donation to support our work: </p>
<table>
<tr>
<td style="padding: 0.5em">
<a href="https://roboticdogs.actionkit.com/donate/funds?amount=5" style="border-radius: 8px; background: green; color: white; padding: 0.5em 1em">Donate $5</a>
</td>
<td style="padding: 0.5em">
<a href="https://roboticdogs.actionkit.com/donate/funds?amount=10" style="border-radius: 8px; background: green; color: white; padding: 0.5em 1em">Donate $10</a>
</td>
</tr>
<tr>
<td style="padding: 0.5em">
<a href="https://roboticdogs.actionkit.com/donate/funds?amount=15" style="border-radius: 8px; background: green; color: white; padding: 0.5em 1em">Donate $15</a>
</td>
<td style="padding: 0.5em">
<a href="https://roboticdogs.actionkit.com/donate/funds?amount=20" style="border-radius: 8px; background: green; color: white; padding: 0.5em 1em">Donate $20</a>
</td>
</tr>
</table>
<p>Thanks for all you do.</p>
Obviously a real mailing would be more complicated but this will serve to illustrate the technique.
Defining a Template String
We can see that there’s a lot of repetition here — made worse by the poor support for style sheets in email clients. It would be helpful if we could pull out a repetitive element and turn it into a sub-template that could be reused whenever it was needed:
{% ... define button ... %}
<a href="https://roboticdogs.actionkit.com/donate/funds?amount={{ amount }}" style="border-radius: 8px; background: green; color: white; padding: 0.5em 1em">Donate ${{ amount }}</a>
{% ... end button ... %}
<table>
<tr>
<td style="padding: 0.5em">
{% ... draw button for 5 ... %}
</td>
<td style="padding: 0.5em">
{% ... draw button for 10 ... %}
</td>
</tr>
<tr>
<td style="padding: 0.5em">
{% ... draw button for 15 ... %}
</td>
<td style="padding: 0.5em">
{% ... draw button for 20 ... %}
</td>
</tr>
</table>
We can accomplish this by storing the sub-template as a string and then evaluating it as a Django template.
The one tricky step here is that we need to include the character sequences {{
and }}
in the template string without evaluating them at the time it is defined; conveniently, Django provides us with a built-in {% templatetag %}
that does precisely this.
{% store as donate_button %}
<a href="https://roboticdogs.actionkit.com/donate/funds?amount={% templatetag openvariable %}amount{% templatetag closevariable %}" style="border-radius: 8px; background: green; color: white; padding: 0.5em 1em">Donate ${% templatetag openvariable %}amount{% templatetag closevariable %}</a>
{% endstore %}
Having defined this template string, we can then invoke it with ActionKit’s {% include_tmpl %}
tag.
<table>
<tr>
<td style="padding: 0.5em">
{% with amount=5 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
<td style="padding: 0.5em">
{% with amount=10 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
</tr>
<tr>
<td style="padding: 0.5em">
{% with amount=15 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
<td style="padding: 0.5em">
{% with amount=20 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
</tr>
</table>
Interpolating template strings will be slightly slower than putting the code inline, but it reduces repetition and makes our code easier to maintain.
Moreover, it provides a way to define a complicated bit of template logic in one place and then invoke it later somewhere else; for example, the sub-template could be defined inside an email wrapper, and then invoked in the body of the mailing itself.
Further Refinements
Let’s go ahead and move the button definition into our email wrapper and give it a bit more flexibility.
We’re going to add an {% if %}
tag to our sub-template, which we want to look like the following:
<a href="https://roboticdogs.actionkit.com/donate/funds?amount={{ amount }}" style="border-radius: 8px; background: {% if suggested %}orange{% else %}green{% endif %}; color: white; padding: 0.5em 1em">Donate ${{ amount }}</a>
After replacing the variable and tag markers with their templatetag
equivalents we wind up with the following, inserted into our email wrapper before the {% block content %}
tag:
{% store as donate_button %}
<a href="https://roboticdogs.actionkit.com/donate/funds?amount={% templatetag openvariable %}amount{% templatetag closevariable %}" style="border-radius: 8px; background: {% templatetag openblock %} if suggested {% templatetag closeblock %}orange{% templatetag openblock %} else {% templatetag closeblock %}green{% templatetag openblock %} endif {% templatetag closeblock %}; color: white; padding: 0.5em 1em">Donate ${% templatetag openvariable %}amount{% templatetag closevariable %}</a>
{% endstore %}
{% block content %}{% endblock content %}
Now that this is in place in the email wrapper, our mailing template can be simplified:
<p>Dear {{ user.first_name|default:"Friend"|title }},</p>
<p> Please make a donation to support our work: </p>
<table>
<tr>
<td style="padding: 0.5em">
{% with amount=5 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
<td style="padding: 0.5em">
{% with amount=10 suggested=1 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
</tr>
<tr>
<td style="padding: 0.5em">
{% with amount=15 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
<td style="padding: 0.5em">
{% with amount=20 %}
{% include_tmpl donate_button %}
{% endwith %}
</td>
</tr>
</table>
<p>Thanks for all you do.</p>
The results are as expected:
Conclusion
Defining sub-templates provides a way to break up our template code into reusable pieces. Complicated chunks of code can then be written by specialists and maintained in the email wrapper, simplifying the template code campaigners have to deal with in the individual mailings.
Leave a Reply