Default tags
All the tags described here are enabled by default in Python Liquid.
Comments
Comments can be used to add documentation to your templates or "comment out" chunks of Liquid markup and text so that it wont be rendered.
Block comments
Block comments start with the comment
tag and end with the endcomment
tag. It is OK for comment text to contain matching comment
/endcomment
or raw
/endraw
pairs, but is a syntax error if comment
or raw
tags are unbalanced.
{% comment %}This is a comment{% endcomment %}
{% comment %}
Comments can
span
multiple lines
{% endcomment %}
Inline comments
An inline comment is a tag called #
. Everything after the hash up to the end tag delimiter (%}
) is comment text. Text can span multiple lines, but each line must start with a #
.
{% # This is a comment %}
{%-
# Comments can span multiple lines,
# but every line must start with a hash.
-%}
Inside liquid tags, any line starting with a hash will be considered a comment.
Output
An expression surrounded by double curly braces, {{
and }}
, is an output statement. When rendered, the expression will be evaluated and the result inserted into the output text.
In this example the expression is a variable, which will be resolved to a value and the value's string representation will output, but output statements can contain any primitive expression.
Primitive expressions
Primitive expression | Examples |
---|---|
Boolean literal | true or false |
Null literal | null or nil |
Integer literal | 123 |
Float literal | 1.23 |
String literal | "Hello" or 'Hello' |
Range | (1..5) or (x..y) |
A path to a variable | foo or foo.bar or foo.bar[0] or foo["some thing"].bar |
Filters
Values can be modified prior to output using filters. Filters are applied to an expression using the pipe symbol (|
), followed by the filter's name and, possibly, some filter arguments. Filter arguments appear after a colon (:
) and are separated by commas (,
).
Multiple filters can be chained together, effectively piping the output of one filter into the input of another. See the filter reference for details of all built in filters.
assign
The assign
tag is used to define and initialize new variables or reassign existing variables.
{% assign foo = "bar" %}
foo is equal to {{ foo }}.
{% assign foo = 42 %}
foo is now equal to {{ foo }}.
The expression on the right-hand side of the assignment operator (=
) follows the syntax described in Output above. It can be any primitive expression and it can include filters.
capture
The capture
tag evaluates the contents of its block and saves the resulting string as a new variable, or reassigns an existing variable, without immediately rendering it.
{% capture welcome_message %}
Hello, {{ customer.name }}! Welcome to our store.
{% endcapture %}
{{ welcome_message }}
In some cases, it can be easier to use a template string.
case
{% case <expression> %}
[ {% when <expression> %} <liquid markup> ] ...
[ {% else %} <liquid markup> ]
{% endcase %}
The case
tag evaluates an expression, matching the result against one or more when
clauses. In the event of a match, the when
block is rendered. The else
clause is rendered if no when
clauses match the case
expression.
{% assign day = "Monday" %}
{% case day %}
{% when "Monday" %}
Start of the work week!
{% when "Friday" %}
It's almost the weekend!
{% when "Saturday" or "Sunday" %}
Enjoy your weekend!
{% else %}
Just another weekday.
{% endcase %}
cycle
Render the next item in an iterator, initializing it and rendering the first value if it does not yet exist. When the items are exhausted, the iterator starts again from the beginning.
You can give cycle
a name to further distinguish multiple iterators with the same items.
decrement
The decrement
tag renders the next value in a named counter, reducing the count by one each time. If a counter with the given name does not already exist, it is created automatically and initialized to zero, before subtracting 1 and outputting -1
.
echo
The echo
tag is equivalent to output statements, an expression surrounded by {{
and }}
, just in tag form. It is mostly used inside {% liquid %}
tags where plain output statements are not allowed.
Hello, {% echo you %}!
Hello, {{ you }}!
{% liquid
for product in collection.products
echo product.title | capitalize
endfor
%}
Just like output statements and the assign
tag, the expression can be any primitive expression and it can include filters.
{% echo "bar" | upcase if x else "baz" | capitalize %}
{% liquid
for product in collection.products
echo product.title | capitalize
endfor
%}
for
{% for <identifier> in <expression>
[ limit: <expression> ] [ offset: <expression> ] [ reversed ] %}
<liquid markup>
[ {% else %} <liquid markup> ]
{% endfor %}
The for
tag renders its block once for each item in an iterable object, like an array/list or mapping/dict/hash. If the iterable is empty and an else
block given, it will be rendered instead.
Range expression are often used with the for
tag to loop over increasing integers.
limit
If a limit
argument is given, the loop will stop after the specified number of iterations.
offset
If an offset
argument is given, it should be an integer specifying how many items to skip before starting the loop.
offset
can also be given the special value "continue"
, in which case the loop will start from where a previous loop with the same iterable left off.
{% for product in collection.products limit: 2 %}
- {{ product.title }}
{% endfor %}
{% for product in collection.products offset: continue %}
- {{ product.title }}!
{% endfor %}
reversed
If the reversed flag is given, the target iterable will be iterated in reverse order.
break
You can exit a loop early using the break
tag.
{% for product in collection.products %}
{% if product.title == "Shirt" %}
{% break %}
{% endif %}
- {{ product.title }}
{% endfor %}
continue
You can skip all or part of a loop iteration with the continue
tag.
{% for product in collection.products %}
{% if product.title == "Shirt" %}
{% continue %}
{% endif %}
- {{ product.title }}
{% endfor %}
forloop
A forloop
object is available inside every for
tag block.
Property | Description | Type |
---|---|---|
name |
The loop variable name and target identifier, separated by a hyphen. | string |
length |
The length of the sequence being iterated. | integer |
index |
The 1-base index of the current iteration. | integer |
index0 |
The 0-base index of the current iteration. | integer |
rindex |
The 1-base index of the current iteration counting from the end. | integer |
rindex0 |
The 0-base index of the current iteration counting from the end. | integer |
first |
true if the current iteration is the first, false otherwise. |
bool |
last |
true is the current iteration is the last, false otherwise. |
bool |
parentloop |
the forloop object of an enclosing for loop. |
forloop |
{% for product in collection.products %}
{% if forloop.first %}
<b>{{ product.title }}</b> - {{ forloop.index0 }}
{% else %}
{{ product.title }} - {{ forloop.index0 }}
{% endif %}
{% endfor %}
if
{% if <expression> %}
<liquid markup>
[ {% elsif <expression> %} <liquid markup> [ {% elsif <expression> %} ... ]]
[ {% else %} <liquid markup> ... ]
{% endif %}
The if
tag conditionally renders its block if its expression evaluates to be truthy. Any number of elsif
blocks can be given to add alternative conditions, and an else
block is used as a default if no preceding conditions were truthy.
{% if product.title == "OK Hat" %}
This hat is OK.
{% elsif product.title == "Rubbish Tie" %}
This tie is rubbish.
{% else %}
Not sure what this is.
{% endif %}
Conditional expressions
Any primitive expression can be tested for truthiness, like {% if some_variable %}
, or you can use a combination of the following operators. Only false
, nil
/null
and the special undefined object are falsy in Liquid.
Operator | Description | Example |
---|---|---|
== |
Equals | product.title == "Nice Shoes" |
!= |
Not equals | user.name != "anonymous" |
> |
Greater than | product.was_price > product.price |
< |
Less than | collection.products.size < 10 |
>= |
Greater than or equal to | user.age >= 18 |
<= |
Less than or equal to | basket.size <= 0 |
and |
Logical and | x and y |
or |
Logical or | x or y |
Operator precedence
In Liquid, and
and or
operators are right associative. Where true and false and false or true
is equivalent to (true and (false and (false or true)))
, evaluating to false
. Python, on the other hand, would parse the same expression as (((true and false) and false) or true)
, evaluating to true
.
include
{% include <template name>
[ ( with | for ) <expression> [ as <identifier> ]]
[[,] <identifier>: <expression> [, [<identifier>: <expression> ... ]]]
%}
The include
tag loads and renders a named template, inserting the resulting text in its place. The name of the template to include can be a string literal or a variable resolving to a string. When rendered, the included template will share the same scope as the current template.
with
Using the optional with
syntax, we can bind a value to a variable that will be in scope for the included template. By default, that variable will be the name of the included template. Alternatively we can specify the variable to use with the as
keyword followed by an identifier.
Here, the template named greeting
will have access to a variable called greeting
with the value "Hello"
.
for
If an array-like object it given following the for
keyword, the named template will be rendered once for each item in the sequence and, like with
above, the item value will be bound to a variable named after the included template.
In this example the template named greeting
will be rendered once with the variable greeting
set to "Hello"
and once with the variable greeting
set to "Goodbye"
.
{% assign greetings = "Hello, Goodbye" | split: ", " %}
{% include "greeting" for greetings as greeting %}
Keyword arguments
Additional keyword arguments given to the include
tag will be added to the included template's scope, then go out of scope after the included template has been rendered.
increment
The increment
tag renders the next value in a named counter, increasing the count by one each time. If a counter with the given name does not already exist, it is created automatically and initialized to zero, which is output before adding 1
.
liquid
The liquid
tag encloses line statements, where each line starts with a tag name and is followed by the tag's expression. Expressions inside liquid
tags must fit on one line as we use \n
as a delimiter indicating the end of the expression.
Note that output statement syntax ({{ <expression> }}
) is not allowed inside liquid
tags, so you must use the echo
tag instead.
{% liquid
assign username = "Brian"
if username
echo "Hello, " | append: username
else
echo "Hello, user"
endif
for i in (1..3)
echo i
endfor
%}
Also, inside liquid
tags, any line starting with a hash will be considered a comment.
raw
Any text between {% raw %}
and {% endraw %}
will not be interpreted as Liquid markup, but output as plain text instead.
render
{% render <string>
[ ( with | for ) <expression> [ as <identifier> ]]
[[,] <identifier>: <expression> [, [<identifier>: <expression> ... ]]]
%}
The render
tag loads and renders a named template, inserting the resulting text in its place. The name of the template to include must be a string literal. When rendered, the included template will have its onw scope, without variables define in the calling template.
with
Using the optional with
syntax, we can bind a value to a variable that will be in scope for the rendered template. By default, that variable will be the name of the rendered template. Alternatively we can specify the variable to use with the as
keyword followed by an identifier.
Here, the template named greeting
will have access to a variable called greeting
with the value "Hello"
.
for
If an array-like object it given following the for
keyword, the named template will be rendered once for each item in the sequence and, like with
above, the item value will be bound to a variable named after the rendered template.
In this example the template named greeting
will be rendered once with the variable greeting
set to "Hello"
and once with the variable greeting
set to "Goodbye"
.
{% assign greetings = "Hello, Goodbye" | split: ", " %}
{% render "greeting" for greetings as greeting %}
Keyword arguments
Additional keyword arguments given to the render
tag will be added to the rendered template's scope, then go out of scope after the it has been rendered.
tablerow
{% tablerow <identifier> in <expression>
[ cols: <expression> ] [ limit: <expression> ] [ offset: <expression> ] %}
<liquid markup>
{% endtablerow %}
The tablerow
tag renders HTML <tr>
and <td>
elements for each item in an iterable. Text inside <td>
elements will be the result of rendering the tag's block.
{
"collection": {
"products": [
{ "title": "Cool Shirt" },
{ "title": "Alien Poster" },
{ "title": "Batman Poster" },
{ "title": "Bullseye Shirt" },
{ "title": "Another Classic Vinyl" },
{ "title": "Awesome Jeans" }
]
}
}
<table>
{% tablerow product in collection.products %}
{{ product.title }}
{% endtablerow %}
</table>
<table>
<tr class="row1">
<td class="col1">Cool Shirt</td>
<td class="col2">Alien Poster</td>
<td class="col3">Batman Poster</td>
<td class="col4">Bullseye Shirt</td>
<td class="col5">Another Classic Vinyl</td>
<td class="col6">Awesome Jeans</td>
</tr>
</table>
cols
By default, tablerow
will output one row with one column for each item in the sequence. Use the cols
parameter to set the number of columns.
<table>
<tr class="row1">
<td class="col1">Cool Shirt</td>
<td class="col2">Alien Poster</td>
</tr>
<tr class="row2">
<td class="col1">Batman Poster</td>
<td class="col2">Bullseye Shirt</td>
</tr>
<tr class="row3">
<td class="col1">Another Classic Vinyl</td>
<td class="col2">Awesome Jeans</td>
</tr>
</table>
limit
If limit
is specified, the tablerow
loop will stop after the given number of iterations.
<table>
{% tablerow product in collection.products limit:2 %}
{{ product.title }}
{% endtablerow %}
</table>
<table>
<tr class="row1">
<td class="col1">Cool Shirt</td>
<td class="col2">Alien Poster</td>
</tr>
</table>
offset
If offset
is specified, the tablerow
loop will start at the given index in the sequence.
<table>
{% tablerow product in collection.products offset:4 %}
{{ product.title }}
{% endtablerow %}
</table>
<table>
<tr class="row1">
<td class="col1">Another Classic Vinyl</td>
<td class="col2">Awesome Jeans</td>
</tr>
</table>
tablerowloop
A tablerowloop
object is available inside every tablerow
block.
Property | Description | Type |
---|---|---|
length |
The length of the sequence being iterated | integer |
index |
The 1-base index of the current iteration | integer |
index0 |
The 0-base index of the current iteration | integer |
rindex |
The 1-base index of the current iteration counting from the end | integer |
rindex0 |
The 0-base index of the current iteration counting from the end | integer |
first |
true if the current iteration is the first, false otherwise |
bool |
last |
true is the current iteration is the last, false otherwise |
bool |
col |
The 1-based column number | integer |
col0 |
The 0-based column number | integer |
col_first |
true if the current column is the first column, false otherwise |
integer |
col_last |
true if the current column is the last column, false otherwise |
integer |
row |
The current row number of the table | integer |
{% tablerow product in collection.products cols:2 %}
{{ product.title }} - {{ tablerowloop.col0 }}
{% endtablerow %}
<table>
<tr class="row1">
<td class="col1">Cool Shirt - 0</td>
<td class="col2">Alien Poster - 1</td>
</tr>
<tr class="row2">
<td class="col1">Batman Poster - 0</td>
<td class="col2">Bullseye Shirt< - 1/td></td>
</tr>
<tr class="row3">
<td class="col1">Another Classic Vinyl - 0</td>
<td class="col2">Awesome Jeans - 1</td>
</tr>
</table>
unless
{% unless <expression> %}
<liquid markup>
[ {% elsif <expression> %} <liquid markup> [ {% elsif <expression> %} ... ]]
[ {% else %} <liquid markup> ... ]
{% endif %}
The unless
tag conditionally renders its block if its expression evaluates to be falsy. Any number of elsif blocks can be given to add alternative conditions, and an else block is used as a default if none of preceding conditions were met.
{% unless product.title == "OK Hat" %}
This hat is OK.
{% elsif product.title == "Rubbish Tie" %}
This tie is rubbish.
{% else %}
Not sure what this is.
{% endif %}
Otherwise unless
behaves the same as if
. See Conditional expressions.