This section describes the Python API for Mako templates. If you are using Mako within a web framework such as Pylons, the work of integrating Mako's API is already done for you, in which case you can skip to the next section, Syntax.
The most basic way to create a template and render it is through the Template
class:
from mako.template import Template
mytemplate = Template("hello world!")
print mytemplate.render()
Above, the text argument to Template
is compiled into a Python module representation. This module contains a function called render_body()
, which produces the output of the template. When mytemplate.render()
is called, Mako sets up a runtime environment for the template and calls the render_body()
function, capturing the output into a buffer and returning its string contents.
The code inside the render_body()
function has access to a namespace of variables. You can specify these variables by sending them as additional keyword arguments to the render()
method:
from mako.template import Template
mytemplate = Template("hello, ${name}!")
print mytemplate.render(name="jack")
The template.render()
method calls upon Mako to create a Context
object, which stores all the variable names accessible to the template and also stores a buffer used to capture output. You can create this Context
yourself and have the template render with it, using the render_context
method:
from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO
mytemplate = Template("hello, ${name}!")
buf = StringIO()
ctx = Context(buf, name="jack")
mytemplate.render_context(ctx)
print buf.getvalue()
A Template
can also load its template source code from a file, using the filename
keyword argument:
from mako.template import Template
mytemplate = Template(filename='/docs/mytmpl.txt')
print mytemplate.render()
For improved performance, a Template
which is loaded from a file can also cache the source code to its generated module on the filesystem as a regular Python module file (i.e. a .py file). To do this, just add the module_directory
argument to the template:
from mako.template import Template
mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules')
print mytemplate.render()
When the above code is rendered, a file /tmp/mako_modules/docs/mytmpl.txt.py
is created containing the source code for the module. The next time a Template
with the same arguments is created, this module file will be automatically re-used.
All of the examples thus far have dealt with the usage of a single Template
object. If the code within those templates tries to locate another template resource, it will need some way to find them, using simple URI strings. For this need, the resolution of other templates from within a template is accomplished by the TemplateLookup
class. This class is constructed given a list of directories in which to search for templates, as well as keyword arguments that will be passed to the Template
objects it creates.
from mako.template import Template
from mako.lookup import TemplateLookup
mylookup = TemplateLookup(directories=['/docs'])
mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup)
Above, we created a textual template which includes the file header.txt
. In order for it to have somewhere to look for header.txt
, we passed a TemplateLookup
object to it, which will search in the directory /docs
for the file header.txt
.
Usually, an application will store most or all of its templates as text files on the filesystem. So far, all of our examples have been a little bit contrived in order to illustrate the basic concepts. But a real application would get most or all of its templates directly from the TemplateLookup
, using the aptly named get_template
method, which accepts the URI of the desired template:
from mako.template import Template
from mako.lookup import TemplateLookup
mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules')
def serve_template(templatename, **kwargs):
mytemplate = mylookup.get_template(templatename)
print mytemplate.render(**kwargs)
In the example above, we create a TemplateLookup
which will look for templates in the /docs
directory, and will store generated module files in the /tmp/mako_modules
directory. The lookup locates templates by appending the given URI to each of its search directories; so if you gave it a URI of /etc/beans/info.txt
, it would search for the file /docs/etc/beans/info.txt
, else raise a TopLevelNotFound
exception, which is a custom Mako exception.
When the lookup locates templates, it will also assign a uri
property to the Template
which is the uri passed to the get_template()
call. Template
uses this uri to calculate the name of its module file. So in the above example, a templatename
argument of /etc/beans/info.txt
will create a module file /tmp/mako_modules/etc/beans/info.txt.py
.
The TemplateLookup
also serves the important need of caching a fixed set of templates in memory at a given time, so that successive uri lookups do not result in full template compilations and/or module reloads on each request. By default, the TemplateLookup
size is unbounded. You can specify a fixed size using the collection_size
argument:
mylookup = TemplateLookup(directories=['/docs'],
module_directory='/tmp/mako_modules', collection_size=500)
The above lookup will continue to load templates into memory until it reaches a count of around 500. At that point, it will clean out a certain percentage of templates using a least recently used scheme.
back to section topAnother important flag on TemplateLookup
is filesystem_checks
. This defaults to True
, and says that each time a template is returned by the get_template()
method, the revision time of the original template file is checked against the last time the template was loaded, and if the file is newer will reload its contents and recompile the template. On a production system, setting filesystem_checks
to False
can afford a small to moderate performance increase (depending on the type of filesystem used).
Both Template
and TemplateLookup
accept output_encoding
and encoding_errors
parameters which can be used to encode the output in any Python supported codec:
from mako.template import Template
from mako.lookup import TemplateLookup
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
mytemplate = mylookup.get_template("foo.txt")
print mytemplate.render()
When using Python 3, the render()
method will return a bytes
object, if output_encoding
is set. Otherwise it returns a string
.
Additionally, the render_unicode()
method exists which will return the template output as a Python unicode
object, or in Python 3 a string
:
print mytemplate.render_unicode()
The above method disregards the output encoding keyword argument; you can encode yourself by saying:
print mytemplate.render_unicode().encode('utf-8', 'replace')
Note that Mako's ability to return data in any encoding and/or unicode
implies that the underlying output stream of the template is a Python unicode object. This behavior is described fully in The Unicode Chapter.
Template exceptions can occur in two distinct places. One is when you lookup, parse and compile the template, the other is when you run the template. Within the running of a template, exceptions are thrown normally from whatever Python code originated the issue. Mako has its own set of exception classes which mostly apply to the lookup and lexer/compiler stages of template construction. Mako provides some library routines that can be used to help provide Mako-specific information about any exception's stack trace, as well as formatting the exception within textual or HTML format. In all cases, the main value of these handlers is that of converting Python filenames, line numbers, and code samples into Mako template filenames, line numbers, and code samples. All lines within a stack trace which correspond to a Mako template module will be converted to be against the originating template file.
To format exception traces, the text_error_template
and html_error_template
functions are provided. They make usage of sys.exc_info()
to get at the most recently thrown exception. Usage of these handlers usually looks like:
from mako import exceptions
try:
template = lookup.get_template(uri)
print template.render()
except:
print exceptions.text_error_template().render()
Or for the HTML render function:
from mako import exceptions
try:
template = lookup.get_template(uri)
print template.render()
except:
print exceptions.html_error_template().render()
The html_error_template
template accepts two options: specifying full=False
causes only a section of an HTML document to be rendered. Specifying css=False
will disable the default stylesheet from being rendered.
E.g.:
print exceptions.html_error_template().render(full=False)
The HTML render function is also available built-in to Template
using the format_exceptions
flag. In this case, any exceptions raised within the render stage of the template will result in the output being substituted with the output of html_error_template
.
template = Template(filename="/foo/bar", format_exceptions=True)
print template.render()
Note that the compile stage of the above template occurs when you construct the Template
itself, and no output stream is defined. Therefore exceptions which occur within the lookup/parse/compile stage will not be handled and will propagate normally. While the pre-render traceback usually will not include any Mako-specific lines anyway, it will mean that exceptions which occur previous to rendering and those which occur within rendering will be handled differently...so the try/except
patterns described previously are probably of more general use.
The underlying object used by the error template functions is the RichTraceback
object. This object can also be used directly to provide custom error views. Here's an example usage which describes its general API:
from mako.exceptions import RichTraceback
try:
template = lookup.get_template(uri)
print template.render()
except:
traceback = RichTraceback()
for (filename, lineno, function, line) in traceback.traceback:
print "File %s, line %s, in %s" % (filename, lineno, function)
print line, "\n"
print "%s: %s" % (str(traceback.error.__class__.__name__), traceback.error)
Further information about RichTraceback
is available within the module-level documentation for mako.exceptions
.
The Mako distribution includes a little bit of helper code for the purpose of using Mako in some popular web framework scenarios. This is a brief description of whats included.
The standard plugin methodology used by Turbogears as well as Pylons is included in the module mako.ext.turbogears
, using the TGPlugin
class. This is also a setuptools entrypoint under the heading python.templating.engines
with the name mako
.
A sample WSGI application is included in the distrubution in the file examples/wsgi/run_wsgi.py
. This runner is set up to pull files from a templates
as well as an htdocs
directory and includes a rudimental two-file layout. The WSGI runner acts as a fully functional standalone web server, using wsgiutils
to run itself, and propagates GET and POST arguments from the request into the Context
, can serve images, css files and other kinds of files, and also displays errors using Mako's included exception-handling utilities.
A Pygments-compatible syntax highlighting module is included under mako.ext.pygmentplugin
. This module is used in the generation of Mako documentation and also contains various setuptools entry points under the heading pygments.lexers
, including mako
, html+mako
, xml+mako
(see the setup.py
file for all the entry points).
Mako provides support for extracting gettext messages from templates via a Babel extractor entry point under mako.ext.babelplugin
.
Gettext messages are extracted from all Python code sections, even the more obscure ones such as control structures, def tag function declarations, call tag exprs and even page tag args.
Translator comments may also be extracted from Mako templates when a comment tag is specified to Babel (such as with the -c option).
For example, a project 'myproj
' contains the following Mako template at myproj/myproj/templates/name.html:
<div id="name">
Name:
## TRANSLATORS: This is a proper name. See the gettext
## manual, section Names.
${_('Francois Pinard')}
</div>
To extract gettext messages from this template the project needs a Mako section in its Babel Extraction Method Mapping file (typically located at myproj/babel.cfg):
# Extraction from Python source files
[python: myproj/**.py]
# Extraction from Mako templates
[mako: myproj/templates/**.html]
input_encoding = utf-8
The Mako extractor supports an optional input_encoding
parameter specifying the encoding of the templates (identical to Template
/TemplateLookup
's input_encoding
parameter).
Invoking Babel's extractor at the command line in the project's root directory:
myproj$ pybabel extract -F babel.cfg -c "TRANSLATORS:" .
Will output a gettext catalog to stdout including the following:
#. TRANSLATORS: This is a proper name. See the gettext
#. manual, section Names.
#: myproj/templates/name.html:5
msgid "Francois Pinard"
msgstr ""
This is only a basic example: Babel can be invoked from setup.py and its command line options specified in the accompanying setup.cfg via Babel Distutils/Setuptools Integration.
Comments must immediately precede a gettext message to be extracted. In the following case the TRANSLATORS: comment would not have been extracted:
<div id="name">
## TRANSLATORS: This is a proper name. See the gettext
## manual, section Names.
Name: ${_('Francois Pinard')}
</div>
See the Babel User Guide for more information.
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.
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, its 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.
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 substituion 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.
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 signficant. The full range of Python "colon" expressions are allowed here, including if/elif/else
, while
, for
, 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
Comments come in two varieties. The single line comment uses ##
as the first non-space characters on a line:
## this is a comment.
...text ...
A multiline version exists using <%doc> ...text... </%doc>
:
<%doc>
these are comments
more comments
</%doc>
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.
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.
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 the order that they appear.
The rest of what Mako offers takes place in the form of tags. All tags use the same syntax, which is similar to an XML tag except that the first character of the tag name is a %
character. The tag is closed either by a contained slash character, or an explicit closing tag:
<%include file="foo.txt"/>
<%def name="foo" buffered="True">
this is a def
</%def>
All tags have a set of attributes which are defined for each tag. Some of these attributes are required. Also, many attributes support evaluation, meaning you can embed an expression (using ${}
) inside the attribute text:
<%include file="/foo/bar/${myfile}.txt"/>
Whether or not an attribute accepts runtime evaluation depends on the type of tag and how that tag is compiled into the template. The best way to find out if you can stick an expression in is to try it ! The lexer will tell you if its not valid.
Heres a quick summary of all the tags:
This tag defines general characteristics of the template, including caching arguments, and optional lists of arguments which the template expects when invoked.
<%page args="x, y, z='default'"/>
Or a page tag that defines caching characteristics:
<%page cached="True" cache_type="memory"/>
Currently, only one <%page>
tag gets used per template, the rest get ignored. While this will be improved in a future release, for now make sure you have only one <%page>
tag defined in your template, else you may not get the results you want. The details of what <%page>
is used for are described further in The "body()" method as well as Caching.
A tag that is familiar from other template languages, %include is a regular joe that just accepts a file argument and calls in the rendered result of that file:
<%include file="header.html"/>
hello world
<%include file="footer.html"/>
Include also accepts arguments which are available as <%page>
arguments in the receiving template:
<%include file="toolbar.html" args="current_section='members', username='ed'"/>
The %def
tag defines a Python function which contains a set of content, that can be called at some other point in the template. The basic idea is simple:
<%def name="myfunc(x)">
this is myfunc, x is ${x}
</%def>
${myfunc(7)}
The %def tag is a lot more powerful than a plain Python def, as the Mako compiler provides many extra services with %def that you wouldn't normally have, such as the ability to export defs as template "methods", automatic propagation of the current Context
, buffering/filtering/caching flags, and def calls with content, which enable packages of defs to be sent as arguments to other def calls (not as hard as it sounds). Get the full deal on what %def can do in Defs.
%namespace is Mako's equivalent of Python's import
statement. It allows access to all the rendering functions and metadata of other template files, plain Python modules, as well as locally defined "packages" of functions.
<%namespace file="functions.html" import="*"/>
The underlying object generated by %namespace, an instance of mako.runtime.Namespace
, is a central construct used in templates to reference template-specific information such as the current URI, inheritance structures, and other things that are not as hard as they sound right here. Namespaces are described in Namespaces.
Inherit allows templates to arrange themselves in inheritance chains. This is a concept familiar in many other template languages.
<%inherit file="base.html"/>
When using the %inherit tag, control is passed to the topmost inherited template first, which then decides how to handle calling areas of content from its inheriting templates. Mako offers a lot of flexbility in this area, including dynamic inheritance, content wrapping, and polymorphic method calls. Check it out in Inheritance.
back to section topAs of Mako 0.2.3, any user-defined "tag" can be created against a namespace by using a tag with a name of the form namespacename:defname. The closed and open formats of such a tag are equivalent to an inline expression and the <%call>
tag, respectively.
<%mynamespace:somedef param="some value">
this is the body
</%mynamespace:somedef>
To create custom tags which accept a body, see Calling a def with embedded content and/or other defs.
back to section topThe call tag is the "classic" form of a user-defined tag, and is roughly equiavlent to the <%namespacename:defname>
syntax described above. This tag is also described in Calling a def with embedded content and/or other defs.
The doc tag handles multiline comments:
<%doc>
these are comments
more comments
</%doc>
Also the ##
symbol as the first non-space characters on a line can be used for single line comments.
This tag suspends the Mako lexer's normal parsing of Mako template directives, and returns its entire body contents as plain text. It is used pretty much to write documentation about Mako:
<%text filter="h">
heres some fake mako ${syntax}
<%def name="x()">${x}</%def>
</%text>
Sometimes you want to stop processing a template or <%def>
method in the middle and just use the text you've accumulated so far. You can use a return
statement inside a Python block to do that.
% if not len(records):
No records found.
<% return %>
% endif
Or perhaps:
<%
if not len(records):
return
%>