A simple tutorial on using the Mako template library in Python

  • 2020-05-07 19:55:38
  • OfStack

Mako is a high performance Python template library that borrows its syntax and API from many other template libraries, such as Django, Jinja2, and so on.
basic usage

The most basic way to create a template and render it is to use the Template class:
 


from mako.template import Template
t = Template('hello world!')
print t.render()

The text parameter passed to Template is compiled into one Python module. The module contains an render_body() function that produces the output of the template. When the render() method is called, Mako sets up a template runtime and calls the render_body() function, saving the output to the buffer and returning its string contents.
The render_body() function can access a set of variables. Additional keyword parameters can be sent to the render() method to specify these variables:
 


from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')

The render() method causes Mako to create an Context object, which stores all the variables that the template can access and a buffer to hold the output. You can also create Context yourself, using the render_context() method to render the template with it:
 


from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO
t = Template('hello, ${name}!')
buf = StringIO()
c = Context(buf, name='yeolar')
t.render_context(c)
print buf.getValue()

USES the file template

Template can also load templates from files, using the filename parameter:
 


from mako.template import Template
t = Template(filename='/docs/tpl.txt')
print t.render()

To improve performance, Template loaded from the file can also cache the generated module as a 1-like Python module file (.py file) in the file system by adding the module_directory parameter:


from mako.template import Template
t = Template(filename='/docs/tpl.txt', module_directory='/tmp/mako_modules')
print t.render()

The code above will render, create 1 / tmp/mako_modules/docs/tpl txt. py files, including source code modules. The next time Template with the same parameter is created, the module file is automatically reused.
USES TemplateLookup

The examples so far have been about the use of a single Template object. If the code in the template wants to locate other template resources, it needs some way to find them using URI. This requirement is met by the TemplateLookup class. This class is constructed by passing in a template to look up a list of directories, then passing the Template object as a keyword parameter:
 


from mako.template import Template
from mako.lookup import TemplateLookup
lookup = TemplateLookup(directories=['/docs'])
t = Template('<%include file="header.txt" /> hello word!', lookup=lookup)

The template created above contains the file header.txt. To find header.txt, an TemplateLookup object is passed to it.
Typically, applications store most or all of the templates on the file system as text files. A real application will get its template directly from TemplateLookup, using the get_template() method, which accepts the URI of the required template as a parameter:
 


from mako.template import Template
from mako.lookup import TemplateLookup
lookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules')
def serve_template(t_name, **kwargs):
  t = lookup.get_template(t_name)
  print t.render(**kwargs)

In the above example we created an TemplateLookup that looks up the template from the /docs directory and stores all the module files in the /tmp/mako_modules directory. By incoming URI attached to each search directory to locate the template, such as pass/etc/beans/info txt, will find file/docs/etc/beans/info txt, if not find will throw TopLevelNotFound anomalies.
When the template is located, URI passed to the get_template() call is also used as the uri attribute of Template. Template use this URI to get module file name, so the above example of/etc beans/info txt will create a module file/tmp/mako_modules/etc/beans/info txt. py.
sets the size of the collection

TemplateLookup also satisfies the requirement to set the total number of templates cached in memory to a fixed value. The default TemplateLookup size is unlimited. One fixed value can be specified with the collection_size parameter:
 


lookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules', collection_size=500)

lookup above loads up to 500 templates into memory. After that, it will clean up the replacement template using the LRU policy.
sets up the file system to check

Another important flag for TemplateLookup is filesystem_checks. The default is True, and each time the get_template() method returns one template, it compares the modification time of the original template file with the last load time of the template, and reloads and compiles the template if the file is updated. In a production system, setting filesystem_checks to False provides some performance improvements.
USES Unicode and encodes

Template and TemplateLookup can set output_encoding and encoding_errors parameters to encode the output to the encoding format supported by Python:
 


from mako.template import Template
from mako.lookup import TemplateLookup
lookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
t = lookup.get_template('foo.txt')
print t.render()

With Python 3, if output_encoding is set, the render() method returns one bytes object, otherwise string.
The render_unicode() method returns the template output as Python unicode object, Python 3 as string:
 


print t.render_unicode()

The above method has no output coded parameters, and can be coded by itself:
 


from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')
0

Note that the underlying output stream of the template in Mako is the Python Unicode object.
handles exceptions

Template exceptions can occur in two places. One is when you find, parse, and compile a template, and one is when you run a template. Exceptions that occur while the template is running are normally thrown at the Python code that caused the problem. Mako has its own set of exception classes, which are primarily used in the find and compile phases of template construction. Mako provides library routines that provide Mako information to the exception stack and output the exception as text or in HTML format. The Python file name, line number, and snippet are converted to the Mako template file name, line number, and snippet. The lines of the Mako template module are converted to the corresponding lines of the original template file.

The text_error_template() and html_error_template() functions are used to format the exception trace. They use sys.exc_info () to get the recently thrown exception. The usage of these processors is as follows:
 


from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')
1

The html_error_template() template accepts two options: specify full=False to render only one section of HTML, and specify css=False to turn off the default stylesheet. Such as:
 


from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')
2

The HTML rendering function can also be added to Template with the format_exceptions flag. In this case, any exception to the template during the render phase is replaced in the output with the output of html_error_template() :
 


t = Template(filename='/foo/bar', format_exceptions=True)
print t.render()

Note that the compilation phase of the above template occurs when Template is constructed, and no output stream is defined. So exceptions that occur during the find, parse, and compile phases are not normally handled, but are propagated. Tracing before rendering does not include lines in the form of Mako, which means that exceptions that occur before and during rendering are handled differently, so try/except may be more commonly used.

The underlying object used by the error template function is the RichTraceback object. This object can also be used directly to provide a custom error view. Here is a sample of one usage:
 


from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')
4

integration Mako
Integrate Mako
in Django

Mako can be integrated with Django's middleware. First you need to install the django-mako module.
In the settings.py file for the Django project, modify MIDDLEWARE_CLASSES and add djangomako.middleware.MakoMiddleware. Use the render_to_response() function to:
 


from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')
5

integrates Mako into Tornado

Mako can be used directly in Tornado. Here is an example:


from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')
6

Related articles: