Syntax¶
A Mako template is parsed from a text stream containing any kind of content, XML, HTML, email text, etc. The template can further contain Mako-specific directives which represent variable and/or expression substitutions, control structures (i.e. conditionals and loops), server-side comments, full blocks of Python code, as well as various tags that offer additional functionality. All of these constructs compile into real Python code. This means that you can leverage the full power of Python in almost every aspect of a Mako template.
Expression Substitution¶
The simplest expression is just a variable substitution. The
syntax for this is the ${}
construct, which is inspired by
Perl, Genshi, JSP EL, and others:
this is x: ${x}
Above, the string representation of x
is applied to the
template’s output stream. If you’re wondering where x
comes
from, it’s usually from the Context
supplied to the
template’s rendering function. If x
was not supplied to the
template and was not otherwise assigned locally, it evaluates to
a special value UNDEFINED
. More on that later.
The contents within the ${}
tag are evaluated by Python
directly, so full expressions are OK:
pythagorean theorem: ${pow(x,2) + pow(y,2)}
The results of the expression are evaluated into a string result in all cases before being rendered to the output stream, such as the above example where the expression produces a numeric result.
Expression Escaping¶
Mako includes a number of built-in escaping mechanisms,
including HTML, URI and XML escaping, as well as a “trim”
function. These escapes can be added to an expression
substitution using the |
operator:
${"this is some text" | u}
The above expression applies URL escaping to the expression, and
produces this+is+some+text
. The u
name indicates URL
escaping, whereas h
represents HTML escaping, x
represents XML escaping, and trim
applies a trim function.
Read more about built-in filtering functions, including how to make your own filter functions, in Filtering and Buffering.
Control Structures¶
A control structure refers to all those things that control the
flow of a program – conditionals (i.e. if
/else
), loops (like
while
and for
), as well as things like try
/except
. In Mako,
control structures are written using the %
marker followed
by a regular Python control expression, and are “closed” by
using another %
marker with the tag “end<name>
”, where
“<name>
” is the keyword of the expression:
% if x==5:
this is some output
% endif
The %
can appear anywhere on the line as long as no text
precedes it; indentation is not significant. The full range of
Python “colon” expressions are allowed here, including
if
/elif
/else
, while
, for
, with
, and even def
,
although Mako has a built-in tag for defs which is more full-featured.
% for a in ['one', 'two', 'three', 'four', 'five']:
% if a[0] == 't':
its two or three
% elif a[0] == 'f':
four/five
% else:
one
% endif
% endfor
The %
sign can also be “escaped”, if you actually want to
emit a percent sign as the first non whitespace character on a
line, by escaping it as in %%
:
%% some text
%% some more text
The Loop Context¶
The loop context provides additional information about a loop
while inside of a % for
structure:
<ul>
% for a in ("one", "two", "three"):
<li>Item ${loop.index}: ${a}</li>
% endfor
</ul>
See The Loop Context for more information on this feature.
New in version 0.7.
Newline Filters¶
The backslash (”\
”) character, placed at the end of any
line, will consume the newline character before continuing to
the next line:
here is a line that goes onto \
another line.
The above text evaluates to:
here is a line that goes onto another line.
Python Blocks¶
Any arbitrary block of python can be dropped in using the <%
%>
tags:
this is a template
<%
x = db.get_resource('foo')
y = [z.element for z in x if x.frobnizzle==5]
%>
% for elem in y:
element: ${elem}
% endfor
Within <% %>
, you’re writing a regular block of Python code.
While the code can appear with an arbitrary level of preceding
whitespace, it has to be consistently formatted with itself.
Mako’s compiler will adjust the block of Python to be consistent
with the surrounding generated Python code.
Module-level Blocks¶
A variant on <% %>
is the module-level code block, denoted
by <%! %>
. Code within these tags is executed at the module
level of the template, and not within the rendering function of
the template. Therefore, this code does not have access to the
template’s context and is only executed when the template is
loaded into memory (which can be only once per application, or
more, depending on the runtime environment). Use the <%! %>
tags to declare your template’s imports, as well as any
pure-Python functions you might want to declare:
<%!
import mylib
import re
def filter(text):
return re.sub(r'^@', '', text)
%>
Any number of <%! %>
blocks can be declared anywhere in a
template; they will be rendered in the resulting module
in a single contiguous block above all render callables,
in the order in which they appear in the source template.
Exiting Early from a Template¶
Sometimes you want to stop processing a template or <%def>
method in the middle and just use the text you’ve accumulated so
far. This is accomplished by using return
statement inside
a Python block. It’s a good idea for the return
statement
to return an empty string, which prevents the Python default return
value of None
from being rendered by the template. This
return value is for semantic purposes provided in templates via
the STOP_RENDERING
symbol:
% if not len(records):
No records found.
<% return STOP_RENDERING %>
% endif
Or perhaps:
<%
if not len(records):
return STOP_RENDERING
%>
In older versions of Mako, an empty string can be substituted for
the STOP_RENDERING
symbol:
<% return '' %>
New in version 1.0.2: - added the STOP_RENDERING
symbol which serves
as a semantic identifier for the empty string ""
used by a
Python return
statement.
Comments¶
Comments come in two varieties. The single line comment uses
##
as the first non-space characters on a line:A multiline version exists using
<%doc> ...text... </%doc>
: