Writing Templates

Templates are just plain text files, with special notation (called ‘tags’) to indicate where the engine should take action.

There are 3 basic types of tags:

  • var
  • block
  • comment

Expressions

At several points in the syntax, an Expression can be used.

An expression can be:

  • an integer
  • a float
  • a string
  • an expression

All expressions start by looking up their first element in the Context. For example the expression name will look for Context[‘name’].

After that, they behave just like Python. You can do a dict or list lookup using [], or call a function using (). Note, however, that function invocations are limited to only positional arguments.

Comments

Comment tags are discarded during parsing, and are only for the benefit of future template editors. They have no impact on rendering performance.

Variables

Var tags are used to display the values of variables. They look like this:

Hello {{ expr }}

Block Tags

Block tags perform some action, may render some output, and may “contain” other tags.

{% include 'another.html' %}

Built In Tags

for

The for tag allows you to loop over a sequence.

{% for x in expr %}
…
{% endfor %}

The for tag also support and else block. It will be used if sequence to be iterated is empty.

{% for x in empty_list %}
…
{% else %}
Nothing to show.
{% endfor %}

if

The if tag allows for simple flow control based on a truthy test.

{% if expr %}
Success!
{% endif %}

It also supports negative cases:

{% if not expr %}
Failure!
{% endif %}

And, like the for tag, it supports an else block:

{% if expr %}
Success!
{% else %}
Failure!
{% endif %}

“Truthiness” is based on the Python concept. Here are some things that are “truthy”:

  • True
  • non-empty strings
  • non-empty lists or dicts
  • non-zero values

Conversely, things that are “falsy” are:

  • False
  • empty strings
  • 0 and 0.0
  • empty lists and dicts

include

The include tag lets you render another template inline, using the current context.

{% include expr %}

Additionally, you can pass extra expressions to be added to the context whilst the other template is being rendered.

{% include form_field.html field=current_field %}

load

This tag lets you load other code modules to add new tags to use in this template. See Tags for more details.

{% load 'myproject.tags' %}

The value passed is a Python import path.

extends and block

The extends tag allows the use of template inheritance. A base template can denote blocks of content which can be overridden by templates which extend it.

Caution

The extends tag only works properly if it is the very first thing in your template.

Say we have the following base template:

<!DOCTYPE html>
<html lan="en">
    <head>
        <title>{% block title %}Welcome!{% endblock %}</title>
        <link rel="stylesheet" type="text/css" href="/static/css/base.css">
        {% block extra_head %}{% endblock %}
    </head>
    <body>
        <header>
            <h1>{% block header %}Welcome!{% endblock %}</h1>
        </header>
        <main>
        {% block content %}{% endblock %}
        </main>
        <footer>
            <p>&copy; 2016 Me!</p>
        </footer>
        {% block footer_scripts %}{% endblock %}
    </body>
</html>

Now, when rendered itself, it will show as:

<!DOCTYPE html>
<html lan="en">
    <head>
        <title>Welcome!</title>
        <link rel="stylesheet" type="text/css" href="/static/css/base.css">

    </head>
    <body>
        <header>
            <h1>Welcome!</h1>
        </header>
        <main>

        </main>
        <footer>
            <p>&copy; 2016 Me!</p>
        </footer>

    </body>
</html>

However, if we write another template which extends this one, we just have to write now the blocks we want to override:

{% extends 'base.html' %}

{% block title %}My Title!{% endblock %}

{% block content %}
Welcome to my first page!
{% endblock %}

This will override only the two given blocks content.

Any content outside of block tags will be ignored.

with

Using with you can temporarily assign new values in the context from expressions. This can help avoid repeated work.

{% with url=make_url(page) %}
<a href="{{ url }}" class="link {% if is_current_url(url) %}current{% endif %}">{{ page.title }}</a>
{% endwith %}

case/when

Allows switching between multiple blocks of template depending on the value of a variable.

{% case foo.bar %}
{% when 1 %}
You got one!
{% when 2 %}
You got two!
{% else %}
You got some!
{% endcase %}

The optional {% else %} clause is used if no when cases match.