pyramid_mako

Overview

pyramid_mako is a set of bindings that makes templates written for the Mako templating system work under the Pyramid web framework. Mako is a templating system written by Mike Bayer.

Installation

  1. Make a virtual environment workspace:

    $ export VENV=~/env
    $ python3 -m venv $VENV
    
  2. Use pip to get pyramid_mako and its direct dependencies installed:

$ $VENV/bin/pip install pyramid_mako

Setup

There are two ways to make sure that pyramid_mako is active. Both are completely equivalent:

  1. Use the includeme function via config.include:

    config.include('pyramid_mako')
    
  2. Put a reference to pyramid_mako within the pyramid.includes value in your ini file configuration:

    pyramid.includes = pyramid_mako
    

Once activated, files with the .mako or .mak extension are considered to be Mako templates.

Usage

Once pyramid_mako has been activated .mako templates can be used by the Pyramid rendering system.

When used as the renderer argument of a view, the view must return a Response object or a Python dict. The Response object would bypass the renderer entirely. Otherwise the items in the dict would be available in the global template space. If the view callable returns anything but a Response object or a dict, an error will likely be raised.

Template Lookup Mechanisms

There are several ways for Pyramid to find your Mako templates.

Asset Specifications

Templates may always be defined using an asset specification. These are strings which define an absolute location of the template, relative to some Python package. For example, myapp.views:templates/home.mako. These specifications are supported throughout Pyramid and provide a fool-proof way to find any supporting assets bundled with your application.

Here’s an example view configuration which uses an asset specification:

1@view_config(renderer='mypackage:templates/foo.mak')
2def hello_world(request):
3    return {'a':'1'}

Asset specifications have some significant benefits in Pyramid, as they are fully overridable. An addon package can ship with code looking to render all of its rendering done using asset specs. Later another package can include the addon and provide customized templates without having to actually modify the addon package. See Overriding Assets for more information.

Caller-Relative Template Lookup

By default, templates are discovered relative to the caller’s package. This means that if you define a view in a Python module, the templates would be found relative to the module’s directory on the filesystem.

Let’s look at an example:

1@view_config(renderer='templates/mytemplate.mako')
2def myview(request):
3    return {'foo': 1, 'bar': 2}

Imagine that the above code is in a myapp.admin.views module. The template would be relative to that module on the filesystem, as shown below:

myapp
|- __init__.py
`- admin
   |- views.py
   `- templates
      `- mytemplate.mako

One significant advantage of this approach over search paths (described below) is that the path is actually converted into an asset specification in the background. This allows the template lookup to be modified using Pyramid’s powerful asset overriding APIs such as config.override_asset.

Caller-relative lookup also avoids naming collisions which can be common in a search path-based approach.

Search Path-Based Template Lookup

When used outside of Pyramid, Mako’s default lookup mechanism is a search path. To use this mechanism within Pyramid, simply define the search path using the mako.directories configuration setting.

Rendering Mako templates with a search path is typically done as follows:

1from pyramid.view import view_config
2
3@view_config(renderer='mytemplate.mako')
4def myview(request):
5    return {'foo':1, 'bar':2}

We are now dependent on our configuration settings to tell us where the template may be located. Commonly a templates directory is created at the base of the package and the configuration file will include the following directive:

mako.directories = mypkg:templates

Templates Including Templates

Mako allows template inheritance as well as other mechanisms for templates to load each other. The lookup mechanisms supported in these cases include asset specifications and template-relative names.

Automatically Reloading Templates

It’s often convenient to see changes you make to a template file appear immediately without needing to restart the application process. Pyramid allows you to configure your application development environment so that a change to a template will be automatically detected, and the template will be reloaded on the next rendering.

Warning

Auto-template-reload behavior is not recommended for production sites as it slows rendering slightly; it’s usually only desirable during development.

In order to turn on automatic reloading of templates, you can use a configuration file setting, or an environment variable.

To use a setting in the application .ini file for the same purpose, set the pyramid.reload_templates key to true within the application’s configuration section, e.g.:

1[app:main]
2use = egg:MyProject
3pyramid.reload_templates = true

To use an environment variable, start your application under a shell using the PYRAMID_RELOAD_TEMPLATES operating system environment variable set to 1, For example:

$ PYRAMID_RELOAD_TEMPLATES=1 bin/pserve myproject.ini

Note

If you are already familiar with the Mako Templating Language, then you should be aware that configuration options for Pyramid and Mako may cause some confusion.

Pyramid offers a universal pyramid.reload_templates setting to manage similar functionality across multiple template systems.

Pyramid’s reload_templates is essentially a proxy to Mako’s filesystem_checks configuration option (with support for some other Pyramid-specific features built in). If reload_templates is set to True, Pyramid will pass filesystem_checks = True to Mako (and vice-versa).

Traditionally in Mako, a TemplateLookup instance will have the default value filesystem_checks = True and one must explicitly disable this behavior. However, Pyramid’s default behavior is for reload_templates to be None, which Mako will treat as a False value for this setting.

Because of this difference, the Mako integration of pyramid_mako may not initially behave as you expect it would. Mako’s filesystem_checks are disabled by default and must be explicitly enabled by setting pyramid.reload_templates to true. You can also affect reload_templates with the environment variable PYRAMID_RELOAD_TEMPLATES as described above.

A Sample Mako Template

Here’s what a simple Mako template used under pyramid_mako might look like:

 1<html>
 2<head>
 3    <title>${project} Application</title>
 4</head>
 5  <body>
 6     <h1 class="title">Welcome to <code>${project}</code>, an
 7      application generated by the <a
 8      href="https://docs.pylonsproject.org/projects/pyramid/en/latest/"
 9     >pyramid</a> web framework.</h1>
10  </body>
11</html>

This template doesn’t use any advanced features of Mako, only the ${} replacement syntax for names that are passed in as renderer globals. See the the Mako documentation to use more advanced features.

Template Variables provided by Pyramid

Pyramid by default will provide a set of variables that are available within your templates, please see System Values Used During Rendering for more information about those variables.

Note

There is one variable that has to be renamed due to having an naming conflict with an internal Mako variable.

context will be renamed to _context

To output the name of the current context you would use the following:

<div>Context name: ${_context.__name__}</div>

Using A Mako def name Within a Renderer Name

Sometimes you’d like to render a def inside of a Mako template instead of the full Mako template. To render a def inside a Mako template, given a Mako template file named foo.mak and a def named bar, you can configure the template as a renderer like so:

1from pyramid.view import view_config
2
3@view_config(renderer='foo#bar.mak')
4def my_view(request):
5    return {'project':'my project'}

The above will render the bar def from within the foo.mak template instead of the entire template.

Adding or Overriding a Renderer

By default, pyramid_mako registers two renderers, one for .mako and another for .mak file extensions. The configuration for these renderers are loaded from the mako. settings in your ini file.

It’s possible to add Mako renderers for alternate file extensions, or override the default .mak and .mako renderers with your own settings using the pyramid_mako.add_mako_renderer() directive.

1config.include('pyramid_mako')
2config.add_mako_renderer('.mak', settings_prefix='mymak.')
3config.add_mako_renderer('.html')
4config.add_mako_renderer('.email', settings_prefix='makoemail.')

At the end of this setup, there will be 4 renderers registered. .mako and .html renderers are loaded from the mako. settings, and .mak is using the mymak. settings. Finally .email templates will be using the makoemail. settings. Some example usage follows:

1from pyramid.renderers import render
2
3@view_config(renderer='foo.html')
4def show_email(request):
5    email_body = render('hello.email', {})
6    return {
7        'email_body': email_body,
8    }

Settings

Mako derives additional settings to configure its template renderer. Many of these settings are optional and only need to be set if they should be different from the default. The below values can be present in the .ini file used to configure the Pyramid application (in the app section representing your Pyramid app) or they can be passed directly within the settings argument passed to a Pyramid Configurator. The Mako Template Renderer uses a subclass of Mako’s template lookup and accepts several arguments to configure it. These settings match those arguments.

Mako Directories

The value(s) supplied here are passed in as the template directories. They should be in asset specification format, for example: my.package:templates would specify the templates folder relative to the location of the my.package Python package.

Config File Setting Name

mako.directories

Mako Caching

The values supplied here are passed in TemplateLookup as the cache_args. More docs about caching in Mako.

Config File Setting Name

mako.cache.timeout

mako.cache.type

mako.cache.url

mako.cache.dir

Setting the cache implementation is done using the cache_impl, the Mako default is to use beaker.

Config File Setting Name

mako.cache_impl

Mako Module Directory

The value supplied here tells Mako where to store compiled Mako templates. If omitted, compiled templates will be stored in memory. This value should be an absolute path, for example: %(here)s/data/templates would use a directory called data/templates in the same parent directory as the INI file. The folder can also be an asset specification, defining a directory relative to the package.

Config File Setting Name

mako.module_directory

Mako Input Encoding

The encoding that Mako templates are assumed to have. By default this is set to utf-8. If you wish to use a different template encoding, this value should be changed accordingly.

Config File Setting Name

mako.input_encoding

Mako Error Handler

A callable (or a dotted Python name which names a callable) which is called whenever Mako 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.

Config File Setting Name

mako.error_handler

Mako Default Filters

List of string filter names that will be applied to all Mako expressions (see Mako Expression Filtering and default_filters). By default, this is set to ['h'] for HTML escaping. If you wish to use Mako’s default filters, this should be set to None.

Config File Setting Name

mako.default_filters

Mako Import

String list of Python statements, typically individual “import” lines, which will be placed into the module level preamble of all generated Python modules.

Config File Setting Name

mako.imports

Mako __future__ Import

String list of Python features to import, defined in __future__ module, named as if they were actually imported with a from __future__ import FEATURE import (see mako.lookup.TemplateLookup future_imports parameter). Equivalent imports will be placed at first line into the module level preamble of all generated Python modules.

Config File Setting Name

mako.future_imports

New in version 1.0.

Mako Strict Undefined

true or false, representing the “strict undefined” behavior of Mako (see Mako Context Variables). By default, this is false.

Config File Setting Name

mako.strict_undefined

Mako Preprocessor

A callable (or a dotted Python name which names a callable) which is called to preprocess the source before the template is called. The callable 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.

Config File Setting Name

mako.preprocessor

Preprocessor - Pyramid Settings

If set to true, the mako.preprocessor will be wrapped in a function that invokes the preprocessor with pyramid’s config settings as the second argument. This will allow the preprocessor to act based upon the settings.

def mako_preprocessor(template, settings):

template = template.replace(“foo”, settings.get(“foo_replacement”)) return template

Config File Setting Name

mako.preprocessor_wants_settings

Reloading Templates

When this value is true, templates are automatically reloaded whenever they are modified without restarting the application, so you can see changes to templates take effect immediately during development. This flag is meaningful to most template rendering add-ons.

Environment Variable Name

Config File Setting Name

PYRAMID_RELOAD_TEMPLATES

pyramid.reload_templates

Unit Testing

When you are running unit tests, you will be required to use config.include('pyramid_mako') to add pyramid_mako so that its renderers are added to the config and can be used.:

from pyramid import testing
from pyramid.response import Response
from pyramid.renderers import render

# The view we want to test
def some_view(request):
    return Response(render('mypkg:templates/home.mako', {'var': 'testing'}))

class TestViews(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp()
        self.config.include('pyramid_mako')

    def tearDown(self):
        testing.tearDown()

    def test_some_view(self):
        from pyramid.testing import DummyRequest
        request = DummyRequest()
        response = some_view(request)
        # templates/home.mako starts with the standard <html> tag for HTML5
        self.assertTrue('<html' in response.body)

API Documentation

Reporting Bugs / Development Versions

Visit https://github.com/Pylons/pyramid_mako to download development or tagged versions.

Visit https://github.com/Pylons/pyramid_mako/issues to report bugs.

Indices and tables