Mako 1.3.0 Documentation

Release: 1.3.0
Mako 1.3.0 Documentation » Usage

Usage

Usage

Basic Usage

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 Template.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 Template.render_context() method:

from mako.template import Template
from mako.runtime import Context
from io import StringIO

mytemplate = Template("hello, ${name}!")
buf = StringIO()
ctx = Context(buf, name="jack")
mytemplate.render_context(ctx)
print(buf.getvalue())

Using File-Based Templates

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.

Using TemplateLookup

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 TemplateLookup.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 TemplateLookup.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.

Setting the Collection Size

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.

Setting Filesystem Checks

Another important flag on TemplateLookup is filesystem_checks. This defaults to True, and says that each time a template is returned by the TemplateLookup.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).

Using Unicode and Encoding

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 Template.render() method will return a bytes object, if output_encoding is set. Otherwise it returns a string.

Additionally, the Template.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.

Handling Exceptions

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))

Common Framework Integrations

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 what’s included.

WSGI

A sample WSGI application is included in the distribution 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.

Pygments

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).

Babel

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, including those of control lines and expressions embedded in tags.

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.

API Reference

Object Name Description

DefTemplate

Bases: Template

html_error_template()

Provides a template that renders a stack trace in an HTML format, providing an excerpt of code as well as substituting source template filenames, line numbers and code for that of the originating source template, as applicable.

RichTraceback

Bases: object

Template

Bases: object

TemplateCollection

Bases: object

TemplateLookup

Bases: TemplateCollection

text_error_template([lookup])

Provides a template that renders a stack trace in a similar format to the Python interpreter, substituting source template filenames, line numbers and code for that of the originating source template, as applicable.

class mako.template.Template(text=None, filename=None, uri=None, format_exceptions=False, error_handler=None, lookup=None, output_encoding=None, encoding_errors='strict', module_directory=None, cache_args=None, cache_impl='beaker', cache_enabled=True, cache_type=None, cache_dir=None, cache_url=None, module_filename=None, input_encoding=None, module_writer=None, default_filters=None, buffer_filters=(), strict_undefined=False, imports=None, future_imports=None, enable_loop=True, preprocessor=None, lexer_cls=None, include_error_handler=None)

Bases: object

Represents a compiled template.

Template includes a reference to the original template source (via the source attribute) as well as the source code of the generated Python module (i.e. the code attribute), as well as a reference to an actual Python module.

Template is constructed using either a literal string representing the template text, or a filename representing a filesystem path to a source file.

Parameters:
  • text – textual template source. This argument is mutually exclusive versus the filename parameter.

  • filename – filename of the source template. This argument is mutually exclusive versus the text parameter.

  • buffer_filters – string list of filters to be applied to the output of %defs which are buffered, cached, or otherwise filtered, after all filters defined with the %def itself have been applied. Allows the creation of default expression filters that let the output of return-valued %defs “opt out” of that filtering via passing special attributes or objects.

  • cache_args – Dictionary of cache configuration arguments that will be passed to the CacheImpl. See Caching.

  • cache_dir

    Deprecated since version 0.6: Use the 'dir' argument in the cache_args dictionary. See Caching.

  • cache_enabled – Boolean flag which enables caching of this template. See Caching.

  • cache_impl – String name of a CacheImpl caching implementation to use. Defaults to 'beaker'.

  • cache_type

    Deprecated since version 0.6: Use the 'type' argument in the cache_args dictionary. See Caching.

  • cache_url

    Deprecated since version 0.6: Use the 'url' argument in the cache_args dictionary. See Caching.

  • default_filters – List of string filter names that will be applied to all expressions. See The default_filters Argument.

  • enable_loop – When True, enable the loop context variable. This can be set to False to support templates that may be making usage of the name “loop”. Individual templates can re-enable the “loop” context by placing the directive enable_loop="True" inside the <%page> tag – see Migrating Legacy Templates that Use the Word “loop”.

  • encoding_errors – Error parameter passed to encode() when string encoding is performed. See Using Unicode and Encoding.

  • error_handler

    Python callable which is called whenever compile or runtime exceptions occur. The callable is passed the current context as well as the exception. If the callable returns True, the exception is considered to be handled, else it is re-raised after the function completes. Is used to provide custom error-rendering functions.

    See also

    Template.include_error_handler - include-specific error handler function

  • format_exceptions – if True, exceptions which occur during the render phase of this template will be caught and formatted into an HTML error page, which then becomes the rendered result of the render() call. Otherwise, runtime exceptions are propagated outwards.

  • imports – String list of Python statements, typically individual “import” lines, which will be placed into the module level preamble of all generated Python modules. See the example in The default_filters Argument.

  • future_imports – String list of names to import from __future__. These will be concatenated into a comma-separated string and inserted into the beginning of the template, e.g. futures_imports=['FOO', 'BAR'] results in from __future__ import FOO, BAR. If you’re interested in using features like the new division operator, you must use future_imports to convey that to the renderer, as otherwise the import will not appear as the first executed statement in the generated code and will therefore not have the desired effect.

  • include_error_handler

    An error handler that runs when this template is included within another one via the <%include> tag, and raises an error. Compare to the Template.error_handler option.

    New in version 1.0.6.

    See also

    Template.error_handler - top-level error handler function

  • input_encoding – Encoding of the template’s source code. Can be used in lieu of the coding comment. See Using Unicode and Encoding as well as The Unicode Chapter for details on source encoding.

  • lookup – a TemplateLookup instance that will be used for all file lookups via the <%namespace>, <%include>, and <%inherit> tags. See Using TemplateLookup.

  • module_directory – Filesystem location where generated Python module files will be placed.

  • module_filename – Overrides the filename of the generated Python module file. For advanced usage only.

  • module_writer

    A callable which overrides how the Python module is written entirely. The callable is passed the encoded source content of the module and the destination path to be written to. The default behavior of module writing uses a tempfile in conjunction with a file move in order to make the operation atomic. So a user-defined module writing function that mimics the default behavior would be:

    import tempfile
    import os
    import shutil
    
    def module_writer(source, outputpath):
        (dest, name) = \\
            tempfile.mkstemp(
                dir=os.path.dirname(outputpath)
            )
    
        os.write(dest, source)
        os.close(dest)
        shutil.move(name, outputpath)
    
    from mako.template import Template
    mytemplate = Template(
                    filename="index.html",
                    module_directory="/path/to/modules",
                    module_writer=module_writer
                )

    The function is provided for unusual configurations where certain platform-specific permissions or other special steps are needed.

  • output_encoding – The encoding to use when render() is called. See Using Unicode and Encoding as well as The Unicode Chapter.

  • preprocessor – Python callable which will be passed the full template source before it is parsed. The return result of the callable will be used as the template source code.

  • lexer_cls

    A Lexer class used to parse the template. The Lexer class is used by default.

    New in version 0.7.4.

  • strict_undefined

    Replaces the automatic usage of UNDEFINED for any undeclared variables not located in the Context with an immediate raise of NameError. The advantage is immediate reporting of missing variables which include the name.

    New in version 0.3.6.

  • uri – string URI or other identifier for this template. If not provided, the uri is generated from the filesystem path, or from the in-memory identity of a non-file-based template. The primary usage of the uri is to provide a key within TemplateLookup, as well as to generate the file path of the generated Python module file, if module_directory is specified.

attribute mako.template.Template.code

Return the module source code for this Template.

method mako.template.Template.get_def(name)

Return a def of this template as a DefTemplate.

method mako.template.Template.list_defs()

return a list of defs in the template.

New in version 1.0.4.

method mako.template.Template.render(*args, **data)

Render the output of this template as a string.

If the template specifies an output encoding, the string will be encoded accordingly, else the output is raw (raw output uses StringIO and can’t handle multibyte characters). A Context object is created corresponding to the given data. Arguments that are explicitly declared by this template’s internal rendering method are also pulled from the given *args, **data members.

method mako.template.Template.render_context(context, *args, **kwargs)

Render this Template with the given context.

The data is written to the context’s buffer.

method mako.template.Template.render_unicode(*args, **data)

Render the output of this template as a unicode object.

attribute mako.template.Template.source

Return the template source code for this Template.

class mako.template.DefTemplate(parent, callable_)

Bases: Template

A Template which represents a callable def in a parent template.

Members

get_def()

method mako.template.DefTemplate.get_def(name)

Return a def of this template as a DefTemplate.

class mako.lookup.TemplateCollection

Bases: object

Represent a collection of Template objects, identifiable via URI.

A TemplateCollection is linked to the usage of all template tags that address other templates, such as <%include>, <%namespace>, and <%inherit>. The file attribute of each of those tags refers to a string URI that is passed to that Template object’s TemplateCollection for resolution.

TemplateCollection is an abstract class, with the usual default implementation being TemplateLookup.

method mako.lookup.TemplateCollection.adjust_uri(uri, filename)

Adjust the given uri based on the calling filename.

When this method is called from the runtime, the filename parameter is taken directly to the filename attribute of the calling template. Therefore a custom TemplateCollection subclass can place any string identifier desired in the filename parameter of the Template objects it constructs and have them come back here.

method mako.lookup.TemplateCollection.filename_to_uri(uri, filename)

Convert the given filename to a URI relative to this TemplateCollection.

method mako.lookup.TemplateCollection.get_template(uri, relativeto=None)

Return a Template object corresponding to the given uri.

The default implementation raises NotImplementedError. Implementations should raise TemplateLookupException if the given uri cannot be resolved.

Parameters:
  • uri – String URI of the template to be resolved.

  • relativeto – if present, the given uri is assumed to be relative to this URI.

method mako.lookup.TemplateCollection.has_template(uri)

Return True if this TemplateLookup is capable of returning a Template object for the given uri.

Parameters:

uri – String URI of the template to be resolved.

class mako.lookup.TemplateLookup(directories=None, module_directory=None, filesystem_checks=True, collection_size=-1, format_exceptions=False, error_handler=None, output_encoding=None, encoding_errors='strict', cache_args=None, cache_impl='beaker', cache_enabled=True, cache_type=None, cache_dir=None, cache_url=None, modulename_callable=None, module_writer=None, default_filters=None, buffer_filters=(), strict_undefined=False, imports=None, future_imports=None, enable_loop=True, input_encoding=None, preprocessor=None, lexer_cls=None, include_error_handler=None)

Bases: TemplateCollection

Represent a collection of templates that locates template source files from the local filesystem.

The primary argument is the directories argument, the list of directories to search:

lookup = TemplateLookup(["/path/to/templates"])
some_template = lookup.get_template("/index.html")

The TemplateLookup can also be given Template objects programatically using put_string() or put_template():

lookup = TemplateLookup()
lookup.put_string("base.html", '''
    <html><body>${self.next()}</body></html>
''')
lookup.put_string("hello.html", '''
    <%include file='base.html'/>

    Hello, world !
''')
Parameters:
  • directories – A list of directory names which will be searched for a particular template URI. The URI is appended to each directory and the filesystem checked.

  • collection_size – Approximate size of the collection used to store templates. If left at its default of -1, the size is unbounded, and a plain Python dictionary is used to relate URI strings to Template instances. Otherwise, a least-recently-used cache object is used which will maintain the size of the collection approximately to the number given.

  • filesystem_checks – When at its default value of True, each call to TemplateLookup.get_template() will compare the filesystem last modified time to the time in which an existing Template object was created. This allows the TemplateLookup to regenerate a new Template whenever the original source has been updated. Set this to False for a very minor performance increase.

  • modulename_callable – A callable which, when present, is passed the path of the source file as well as the requested URI, and then returns the full path of the generated Python module file. This is used to inject alternate schemes for Python module location. If left at its default of None, the built in system of generation based on module_directory plus uri is used.

All other keyword parameters available for Template are mirrored here. When new Template objects are created, the keywords established with this TemplateLookup are passed on to each new Template.

method mako.lookup.TemplateLookup.adjust_uri(uri, relativeto)

Adjust the given uri based on the given relative URI.

method mako.lookup.TemplateLookup.filename_to_uri(filename)

Convert the given filename to a URI relative to this TemplateCollection.

method mako.lookup.TemplateLookup.get_template(uri)

Return a Template object corresponding to the given uri.

Note

The relativeto argument is not supported here at the moment.

method mako.lookup.TemplateLookup.put_string(uri, text)

Place a new Template object into this TemplateLookup, based on the given string of text.

method mako.lookup.TemplateLookup.put_template(uri, template)

Place a new Template object into this TemplateLookup, based on the given Template object.

class mako.exceptions.RichTraceback(error=None, traceback=None)

Bases: object

Pull the current exception from the sys traceback and extracts Mako-specific template information.

See the usage examples in Handling Exceptions.

attribute mako.exceptions.RichTraceback.error

the exception instance.

attribute mako.exceptions.RichTraceback.message

the exception error message as unicode.

attribute mako.exceptions.RichTraceback.source

source code of the file where the error occurred. If the error occurred within a compiled template, this is the template source.

attribute mako.exceptions.RichTraceback.lineno

line number where the error occurred. If the error occurred within a compiled template, the line number is adjusted to that of the template source.

attribute mako.exceptions.RichTraceback.records

a list of 8-tuples containing the original python traceback elements, plus the filename, line number, source line, and full template source for the traceline mapped back to its originating source template, if any for that traceline (else the fields are None).

attribute mako.exceptions.RichTraceback.reverse_records

the list of records in reverse traceback – a list of 4-tuples, in the same format as a regular python traceback, with template-corresponding traceback records replacing the originals.

attribute mako.exceptions.RichTraceback.reverse_traceback

the traceback list in reverse.

function mako.exceptions.html_error_template()

Provides a template that renders a stack trace in an HTML format, providing an excerpt of code as well as substituting source template filenames, line numbers and code for that of the originating source template, as applicable.

The template’s default encoding_errors value is 'htmlentityreplace'. The template has two options. With the full option disabled, only a section of an HTML document is returned. With the css option disabled, the default stylesheet won’t be included.

function mako.exceptions.text_error_template(lookup=None)

Provides a template that renders a stack trace in a similar format to the Python interpreter, substituting source template filenames, line numbers and code for that of the originating source template, as applicable.