Jinja2 Support

Accent CMS templates use Jinja2 syntax. This page is a complete reference of every built-in filter, test, function, and syntax construct available to theme developers and content authors.

For Accent CMS-specific template features (custom filters, page context, collections), see the Templating Guide.

Template Syntax

Variables

Output a value with double curly braces:

{{ page.title }}
{{ site.name }}

Tags

Execute logic with {% %} blocks:

{% if page.tags %}
  Tagged content
{% endif %}

{% for item in items %}
  {{ item.title }}
{% endfor %}

Comments

Comments are stripped from output:

{# This is a comment #}

Template Inheritance

Define a base layout with replaceable blocks:

{# base.html.jinja #}
<html>
<body>
  {% block content %}default content{% endblock %}
</body>
</html>

Child templates extend the base and override blocks:

{# page.html.jinja #}
{% extends "base.html.jinja" %}
{% block content %}
  <h1>{{ page.title }}</h1>
  {{ page.content | safe }}
{% endblock %}

The child template’s block content replaces the parent’s. Blocks not overridden keep their default content.

Includes

Pull in another template fragment:

{% include "partials/header.html.jinja" %}

The included template has access to the current context.

Macros

Define reusable template functions:

{# macros.html.jinja #}
{% macro button(label, url) %}
  <a href="{{ url }}" class="btn">{{ label }}</a>
{% endmacro %}

Import and use macros in other templates:

{% from "macros.html.jinja" import button %}
{{ button("Click me", "/action") }}

Whitespace Control

Add a hyphen to strip whitespace around tags:

{%- if true -%}
  tight
{%- endif -%}

This produces tight with no surrounding whitespace. Works with {{- -}} for expressions too.

Auto-escaping

HTML special characters in variable output are automatically escaped:

{# If user_input = "<script>alert(1)</script>" #}
{{ user_input }}
{# Output: &lt;script&gt;alert(1)&lt;/script&gt; #}

Use the safe filter to output trusted HTML without escaping:

{{ page.content | safe }}

For Loops

Basic Loop

{% for item in items %}
  {{ item }}
{% endfor %}

Loop Object

Inside a for loop, the loop variable provides iteration metadata:

PropertyDescription
loop.indexCurrent iteration (1-indexed)
loop.index0Current iteration (0-indexed)
loop.revindexIterations remaining (1-indexed)
loop.revindex0Iterations remaining (0-indexed)
loop.firsttrue on the first iteration
loop.lasttrue on the last iteration
loop.lengthTotal number of items
loop.depthNesting depth (starts at 1)
loop.depth0Nesting depth (starts at 0)

Example:

{% for page in pages %}
  {{ loop.index }}/{{ loop.length }}: {{ page.title }}
  {% if loop.first %}(first){% endif %}
  {% if loop.last %}(last){% endif %}
{% endfor %}

Built-in Filters

Filters transform values using the pipe (|) operator: {{ value|filter }}.

String Filters

FilterExampleResult
capitalize{{ "hello WORLD"|capitalize }}Hello world
lower{{ "HELLO"|lower }}hello
upper{{ "hello"|upper }}HELLO
title{{ "hello world"|title }}Hello World
trim{{ " hello "|trim }}hello
replace{{ "hello"|replace("l", "r") }}herro
split{{ "a,b,c"|split(",") }}["a", "b", "c"]
lines{{ "a\nb\nc"|lines|list }}["a", "b", "c"]
indent{{ "a\nb"|indent(4) }}Indented lines
format{{ "%s is %d"|format("age", 30) }}age is 30

Number Filters

FilterExampleResult
abs{{ (-3)|abs }}3
float{{ "3.14"|float }}3.14
int{{ "42"|int }}42
round{{ 3.456|round(2) }}3.46

List Filters

FilterExampleResult
first{{ [10, 20, 30]|first }}10
last{{ [10, 20, 30]|last }}30
length{{ [1, 2, 3]|length }}3
join{{ ["a", "b", "c"]|join(", ") }}a, b, c
reverse{{ "abc"|reverse }}cba
sort{{ [3, 1, 2]|sort }}[1, 2, 3]
unique{{ [1, 2, 2, 3]|unique|list }}[1, 2, 3]
min{{ [3, 1, 2]|min }}1
max{{ [3, 1, 2]|max }}3
sum{{ [1, 2, 3]|sum }}6
batch{{ [1,2,3,4,5]|batch(2)|list }}[[1, 2], [3, 4], [5]]
slice{{ [1,2,3,4,5]|slice(2)|list }}[[1, 2, 3], [4, 5]]
chain{{ [1, 2]|chain([3, 4])|list }}[1, 2, 3, 4]
zip{{ [1, 2]|zip(["a", "b"])|list }}[[1, "a"], [2, "b"]]

Selection Filters

FilterExampleResult
select{{ [1,2,3,4]|select("odd")|list }}[1, 3]
reject{{ [1,2,3,4]|reject("odd")|list }}[2, 4]
selectattr{{ items|selectattr("active")|list }}Items where active is truthy
rejectattr{{ items|rejectattr("draft")|list }}Items where draft is falsy
map{{ items|map(attribute="title")|list }}List of title values
groupby{{ items|groupby("category") }}Items grouped by category

Dictionary Filters

FilterExampleResult
items{{ {"a": 1}|items|list }}[["a", 1]]
dictsort{{ {"b": 2, "a": 1}|dictsort }}[["a", 1], ["b", 2]]
attr{{ obj|attr("name") }}Value of obj.name

Type Conversion Filters

FilterExampleResult
bool{{ ""|bool }}false
int{{ "42"|int }}42
float{{ "3.14"|float }}3.14
string{{ 42|string }}42
list{{ "abc"|list }}["a", "b", "c"]

Output Filters

FilterExampleResult
default{{ missing|default("fallback") }}fallback
escape / e{{ "<b>"|escape }}&lt;b&gt;
safe{{ "<b>bold</b>"|safe }}<b>bold</b> (no escaping)
pprint{{ value|pprint }}Debug representation

Built-in Tests

Tests check conditions using the is operator: {% if value is test %}.

Type Tests

TestExampleTrue when
booleanvalue is booleanValue is true or false
integervalue is integerValue is an integer
floatvalue is floatValue is a floating-point number
numbervalue is numberValue is any number (integer or float)
stringvalue is stringValue is a string
sequencevalue is sequenceValue is a list/array
mappingvalue is mappingValue is a dictionary/object
iterablevalue is iterableValue can be iterated over

Value Tests

TestExampleTrue when
truevalue is trueValue is exactly true
falsevalue is falseValue is exactly false
sameasa is sameas ba and b are the same object
in1 is in [1, 2, 3]Value is contained in the sequence

Comparison Tests

TestExampleTrue when
eq / equalto / ==value is eq 1Equal to
ne / !=value is ne 2Not equal to
gt / greaterthan / >value is gt 5Greater than
ge / >=value is ge 5Greater than or equal
lt / lessthan / <value is lt 5Less than
le / <=value is le 5Less than or equal

Number Tests

TestExampleTrue when
oddvalue is oddValue is an odd number
evenvalue is evenValue is an even number
divisiblebyvalue is divisibleby(3)Value is divisible by the argument

String Tests

TestExampleTrue when
lowervalue is lowerAll characters are lowercase
uppervalue is upperAll characters are uppercase
startingwithvalue is startingwith "foo"String starts with the argument
endingwithvalue is endingwith "bar"String ends with the argument

Introspection Tests

TestExampleTrue when
filter"lower" is filterThe named filter exists
test"boolean" is testThe named test exists

Built-in Functions

Functions are called directly in expressions.

range

Generate a sequence of numbers:

{{ range(5)|list }}
{# [0, 1, 2, 3, 4] #}

{{ range(2, 8)|list }}
{# [2, 3, 4, 5, 6, 7] #}

{{ range(0, 10, 2)|list }}
{# [0, 2, 4, 6, 8] #}

dict

Create a dictionary:

{{ dict(name="Alice", age=30) }}

Can merge with an existing dictionary:

{% set base = {"a": 1, "b": 2} %}
{{ dict(base, c=3) }}

namespace

Create a mutable namespace object. Useful for updating values inside loops (regular variables are scoped to blocks):

{% set ns = namespace(count=0) %}
{% for item in items %}
  {% set ns.count = ns.count + 1 %}
{% endfor %}
Total: {{ ns.count }}

debug

Output debug information about a value. Accent requires a value argument:

{{ debug(page) }}

Returns a string representation of the given value. Useful during template development.