Control Statements

2026-06-23

If Statement

Determines which branch to output by evaluating whether an expression is true or false. Syntax keywords: if, else, elif, endif. if and endif are required and must appear in pairs.

{% if price < 10 or always_show %}
   Price is {{ price }}.
{% elif price > 1000 and not rich %}
   That's expensive!
{% else %}
    N/A
{% endif %}

Undefined variables are considered false, so they can be used in if statements to test whether a variable is defined without causing an error.

{% if my_var %}
    {{ my_var }}
{% else %}
    Sorry, my_var isn't defined.
{% endif %}

For Statement

Iterates over each item in a list. Syntax keywords: for, endfor; they must appear in pairs.

{% for product in products %}
  {{loop.index}}. {{product.name}}
{% endfor %}

Or iterate over each character in a string:

{% for letter in name %}
  {% if loop.index % 2 == 0%}
    <span style="color:red">{{ letter }}</span>
  {% else %}
    <span style="color:blue">{{ letter }}</span>
  {% endif %}
{% endfor %}

A loop object variable is predefined inside the loop body with the following available properties:

  • loop.index: current iteration number, starting from 1
  • loop.index0: current iteration number, starting from 0
  • loop.first: whether this is the first iteration
  • loop.last: whether this is the last iteration

Include Statement

The include statement can include other templates. Syntax: include <template path>. Paths are always resolved from the template root directory and must not start with /. Relative paths are not currently supported.

{% include "included.html" %}

The path can be a string expression:

{% include "partials/" ~ name ~ ".html" %}

Included templates:

  • Share the current context data
  • Newly assigned variables are only valid within the included template

A missing template will cause an error. Use the optional keyword to silently ignore a template that does not exist.

{% include "header.html" optional %}

The include statement supports a path list. The first template that exists is included; others are ignored. The optional keyword is also supported in this case.

{% include ["custom/header.html", "header.html"] %}
{% include ["special_sidebar.html", "sidebar.html"] optional %}

Macros Statement

A macro can be thought of as a special type of function. Its internal context is passed through parameters and isolated from the outside. The macro's rendered output is returned as a whole.

{% macro input(label, type="text") %}
    <label>
        {{ label }}
        <input type="{{type}}" />
    </label>
{% endmacro input %}

Macro parameters support constant default values. Parameter values can be valid variables, filters, or functions.

Macros must be defined in a separate template file, then imported and assigned a namespace:

{% import "macros.html" as macros %}

Invocation syntax:

{{ macros::input(label="Name", type="text") }}

Within a macro definition file, when you need to call other macros in the same file, use the self namespace. The self namespace also enables recursive calls -- be careful to ensure a termination condition.

{% macro factorial(n) %}
  {% if n > 1 %}{{ n }} - {{ self::factorial(n=n-1) }}{% else %}1{% endif %}
{% endmacro factorial %}

Macro modules support all syntax except block and extends.