Multiple Pages | One Page

Mako Documentation

Version: 0.1.2 Last Updated: 01/31/07 23:24:25
Next: Syntax

Table of Contents


Basic 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 it's 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()

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.

back to section top

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

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.

back to section top

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 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, seting filesystem_checks to False can afford a small to moderate performance increase (depending on the type of filesystem used).

back to section top

Using Unicode and Encoding

Both Template and TemplateLookup accept an output_encoding parameter 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')

mytemplate = mylookup.get_template("foo.txt")
print mytemplate.render()

Additionally, the render_unicode() method exists which will return the template output as a Python unicode object:

print mytemplate.render_unicode()

The above method disgards the output encoding keyword argument; you can encode yourself by saying:

print mytemplate.render_unicode().encode('utf-8')

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.

back to section top

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 whats included.

Turbogears/Pylons Plugin

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.

back to section top

WSGI

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

back to section top

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

back to section top
Next: Syntax

Table of Contents