Mako 1.2.4 Documentation

Release: 1.2.4
Mako 1.2.4 Documentation » Namespaces

Namespaces

Namespaces

Namespaces are used to organize groups of defs into categories, and also to “import” defs from other files.

If the file components.html defines these two defs:

## components.html
<%def name="comp1()">
    this is comp1
</%def>

<%def name="comp2(x)">
    this is comp2, x is ${x}
</%def>

you can make another file, for example index.html, that pulls those two defs into a namespace called comp:

## index.html
<%namespace name="comp" file="components.html"/>

Here's comp1:  ${comp.comp1()}
Here's comp2:  ${comp.comp2(x=5)}

The comp variable above is an instance of Namespace, a proxy object which delivers method calls to the underlying template callable using the current context.

<%namespace> also provides an import attribute which can be used to pull the names into the local namespace, removing the need to call it via the “.” operator. When import is used, the name attribute is optional.

<%namespace file="components.html" import="comp1, comp2"/>

Heres comp1:  ${comp1()}
Heres comp2:  ${comp2(x=5)}

import also supports the “*” operator:

<%namespace file="components.html" import="*"/>

Heres comp1:  ${comp1()}
Heres comp2:  ${comp2(x=5)}

The names imported by the import attribute take precedence over any names that exist within the current context.

Note

In current versions of Mako, usage of import='*' is known to decrease performance of the template. This will be fixed in a future release.

The file argument allows expressions – if looking for context variables, the context must be named explicitly:

<%namespace name="dyn" file="${context['namespace_name']}"/>

Ways to Call Namespaces

There are essentially four ways to call a function from a namespace.

The “expression” format, as described previously. Namespaces are just Python objects with functions on them, and can be used in expressions like any other function:

${mynamespace.somefunction('some arg1', 'some arg2', arg3='some arg3', arg4='some arg4')}

Synonymous with the “expression” format is the “custom tag” format, when a “closed” tag is used. This format, introduced in Mako 0.2.3, allows the usage of a “custom” Mako tag, with the function arguments passed in using named attributes:

<%mynamespace:somefunction arg1="some arg1" arg2="some arg2" arg3="some arg3" arg4="some arg4"/>

When using tags, the values of the arguments are taken as literal strings by default. To embed Python expressions as arguments, use the embedded expression format:

<%mynamespace:somefunction arg1="${someobject.format()}" arg2="${somedef(5, 12)}"/>

The “custom tag” format is intended mainly for namespace functions which recognize body content, which in Mako is known as a “def with embedded content”:

<%mynamespace:somefunction arg1="some argument" args="x, y">
    Some record: ${x}, ${y}
</%mynamespace:somefunction>

The “classic” way to call defs with embedded content is the <%call> tag:

<%call expr="mynamespace.somefunction(arg1='some argument')" args="x, y">
    Some record: ${x}, ${y}
</%call>

For information on how to construct defs that embed content from the caller, see Calling a Def with Embedded Content and/or Other Defs.

Namespaces from Regular Python Modules

Namespaces can also import regular Python functions from modules. These callables need to take at least one argument, context, an instance of Context. A module file some/module.py might contain the callable:

def my_tag(context):
    context.write("hello world")
    return ''

A template can use this module via:

<%namespace name="hw" module="some.module"/>

${hw.my_tag()}

Note that the context argument is not needed in the call; the Namespace tag creates a locally-scoped callable which takes care of it. The return '' is so that the def does not dump a None into the output stream – the return value of any def is rendered after the def completes, in addition to whatever was passed to Context.write() within its body.

If your def is to be called in an “embedded content” context, that is as described in Calling a Def with Embedded Content and/or Other Defs, you should use the supports_caller() decorator, which will ensure that Mako will ensure the correct “caller” variable is available when your def is called, supporting embedded content:

from mako.runtime import supports_caller

@supports_caller
def my_tag(context):
    context.write("<div>")
    context['caller'].body()
    context.write("</div>")
    return ''

Capturing of output is available as well, using the outside-of-templates version of the capture() function, which accepts the “context” as its first argument:

from mako.runtime import supports_caller, capture

@supports_caller
def my_tag(context):
    return "<div>%s</div>" % \
            capture(context, context['caller'].body, x="foo", y="bar")

Declaring Defs in Namespaces

The <%namespace> tag supports the definition of <%def>s directly inside the tag. These defs become part of the namespace like any other function, and will override the definitions pulled in from a remote template or module:

## define a namespace
<%namespace name="stuff">
    <%def name="comp1()">
        comp1
    </%def>
</%namespace>

## then call it
${stuff.comp1()}

The body() Method

Every namespace that is generated from a template contains a method called body(). This method corresponds to the main body of the template, and plays its most important roles when using inheritance relationships as well as def-calls-with-content.

Since the body() method is available from a namespace just like all the other defs defined in a template, what happens if you send arguments to it? By default, the body() method accepts no positional arguments, and for usefulness in inheritance scenarios will by default dump all keyword arguments into a dictionary called pageargs. But if you actually want to get at the keyword arguments, Mako recommends you define your own argument signature explicitly. You do this via using the <%page> tag:

<%page args="x, y, someval=8, scope='foo', **kwargs"/>

A template which defines the above signature requires that the variables x and y are defined, defines default values for someval and scope, and sets up **kwargs to receive all other keyword arguments. If **kwargs or similar is not present, the argument **pageargs gets tacked on by Mako. When the template is called as a top-level template (i.e. via Template.render()) or via the <%include> tag, the values for these arguments will be pulled from the Context. In all other cases, i.e. via calling the body() method, the arguments are taken as ordinary arguments from the method call. So above, the body might be called as:

${self.body(5, y=10, someval=15, delta=7)}

The Context object also supplies a Context.kwargs accessor, for cases when you’d like to pass along the top level context arguments to a body() callable:

${next.body(**context.kwargs)}

The usefulness of calls like the above become more apparent when one works with inheriting templates. For more information on this, as well as the meanings of the names self and next, see Inheritance.

Built-in Namespaces

The namespace is so great that Mako gives your template one (or two) for free. The names of these namespaces are local and self. Other built-in namespaces include parent and next, which are optional and are described in Inheritance.

local

The local namespace is basically the namespace for the currently executing template. This means that all of the top level defs defined in your template, as well as your template’s body() function, are also available off of the local namespace.

The local namespace is also where properties like uri, filename, and module and the get_namespace method can be particularly useful.

self

The self namespace, in the case of a template that does not use inheritance, is synonymous with local. If inheritance is used, then self references the topmost template in the inheritance chain, where it is most useful for providing the ultimate form of various “method” calls which may have been overridden at various points in an inheritance chain. See Inheritance.

Inheritable Namespaces

The <%namespace> tag includes an optional attribute inheritable="True", which will cause the namespace to be attached to the self namespace. Since self is globally available throughout an inheritance chain (described in the next section), all the templates in an inheritance chain can get at the namespace imported in a super-template via self.

## base.html
<%namespace name="foo" file="foo.html" inheritable="True"/>

${next.body()}

## somefile.html
<%inherit file="base.html"/>

${self.foo.bar()}

This allows a super-template to load a whole bunch of namespaces that its inheriting templates can get to, without them having to explicitly load those namespaces themselves.

The import="*" part of the <%namespace> tag doesn’t yet interact with the inheritable flag, so currently you have to use the explicit namespace name off of self, followed by the desired function name. But more on this in a future release.

Namespace API Usage Example - Static Dependencies

The <%namespace> tag at runtime produces an instance of Namespace. Programmatic access of Namespace can be used to build various kinds of scaffolding in templates and between templates.

A common request is the ability for a particular template to declare “static includes” - meaning, the usage of a particular set of defs requires that certain Javascript/CSS files are present. Using Namespace as the object that holds together the various templates present, we can build a variety of such schemes. In particular, the Context has a namespaces attribute, which is a dictionary of all Namespace objects declared. Iterating the values of this dictionary will provide a Namespace object for each time the <%namespace> tag was used, anywhere within the inheritance chain.

Version One - Use Namespace.attr

The Namespace.attr attribute allows us to locate any variables declared in the <%! %> of a template.

## base.mako
## base-most template, renders layout etc.
<html>
<head>
## traverse through all namespaces present,
## look for an attribute named 'includes'
% for ns in context.namespaces.values():
    % for incl in getattr(ns.attr, 'includes', []):
        ${incl}
    % endfor
% endfor
</head>
<body>
${next.body()}
</body
</html>

## library.mako
## library functions.
<%!
    includes = [
        '<link rel="stylesheet" type="text/css" href="mystyle.css"/>',
        '<script type="text/javascript" src="functions.js"></script>'
    ]
%>

<%def name="mytag()">
    <form>
        ${caller.body()}
    </form>
</%def>

## index.mako
## calling template.
<%inherit file="base.mako"/>
<%namespace name="foo" file="library.mako"/>

<%foo:mytag>
    a form
</%foo:mytag>

Above, the file library.mako declares an attribute includes inside its global <%! %> section. index.mako includes this template using the <%namespace> tag. The base template base.mako, which is the inherited parent of index.mako and is responsible for layout, then locates this attribute and iterates through its contents to produce the includes that are specific to library.mako.

Version Two - Use a specific named def

In this version, we put the includes into a <%def> that follows a naming convention.

## base.mako
## base-most template, renders layout etc.
<html>
<head>
## traverse through all namespaces present,
## look for a %def named 'includes'
% for ns in context.namespaces.values():
    % if hasattr(ns, 'includes'):
        ${ns.includes()}
    % endif
% endfor
</head>
<body>
${next.body()}
</body
</html>

## library.mako
## library functions.

<%def name="includes()">
    <link rel="stylesheet" type="text/css" href="mystyle.css"/>
    <script type="text/javascript" src="functions.js"></script>
</%def>

<%def name="mytag()">
    <form>
        ${caller.body()}
    </form>
</%def>


## index.mako
## calling template.
<%inherit file="base.mako"/>
<%namespace name="foo" file="library.mako"/>

<%foo:mytag>
    a form
</%foo:mytag>

In this version, library.mako declares a <%def> named includes. The example works identically to the previous one, except that base.mako looks for defs named include on each namespace it examines.

API Reference

Object Name Description

capture(context, callable_, *args, **kwargs)

Execute the given template def, capturing the output into a buffer.

ModuleNamespace

Bases: Namespace

Namespace

Bases: object

supports_caller(func)

Apply a caller_stack compatibility decorator to a plain Python function.

TemplateNamespace

Bases: Namespace

class mako.runtime.Namespace(name, context, callables=None, inherits=None, populate_self=True, calling_uri=None)

Bases: object

Provides access to collections of rendering methods, which can be local, from other templates, or from imported modules.

To access a particular rendering method referenced by a Namespace, use plain attribute access:

${some_namespace.foo(x, y, z)}

Namespace also contains several built-in attributes described here.

attribute mako.runtime.Namespace.attr

Access module level attributes by name.

This accessor allows templates to supply “scalar” attributes which are particularly handy in inheritance relationships.

attribute mako.runtime.Namespace.cache

Return the Cache object referenced by this Namespace object’s Template.

attribute mako.runtime.Namespace.context = None

The Context object for this Namespace.

Namespaces are often created with copies of contexts that contain slightly different data, particularly in inheritance scenarios. Using the Context off of a Namespace one can traverse an entire chain of templates that inherit from one-another.

attribute mako.runtime.Namespace.filename = None

The path of the filesystem file used for this Namespace’s module or template.

If this is a pure module-based Namespace, this evaluates to module.__file__. If a template-based namespace, it evaluates to the original template file location.

method mako.runtime.Namespace.get_cached(key, **kwargs)

Return a value from the Cache referenced by this Namespace object’s Template.

The advantage to this method versus direct access to the Cache is that the configuration parameters declared in <%page> take effect here, thereby calling up the same configured backend as that configured by <%page>.

method mako.runtime.Namespace.get_namespace(uri)

Return a Namespace corresponding to the given uri.

If the given uri is a relative URI (i.e. it does not contain a leading slash /), the uri is adjusted to be relative to the uri of the namespace itself. This method is therefore mostly useful off of the built-in local namespace, described in local.

In most cases, a template wouldn’t need this function, and should instead use the <%namespace> tag to load namespaces. However, since all <%namespace> tags are evaluated before the body of a template ever runs, this method can be used to locate namespaces using expressions that were generated within the body code of the template, or to conditionally use a particular namespace.

method mako.runtime.Namespace.get_template(uri)

Return a Template from the given uri.

The uri resolution is relative to the uri of this Namespace object’s Template.

method mako.runtime.Namespace.include_file(uri, **kwargs)

Include a file at the given uri.

attribute mako.runtime.Namespace.module = None

The Python module referenced by this Namespace.

If the namespace references a Template, then this module is the equivalent of template.module, i.e. the generated module for the template.

attribute mako.runtime.Namespace.template = None

The Template object referenced by this Namespace, if any.

attribute mako.runtime.Namespace.uri = None

The URI for this Namespace’s template.

I.e. whatever was sent to TemplateLookup.get_template().

This is the equivalent of Template.uri.

class mako.runtime.TemplateNamespace(name, context, template=None, templateuri=None, callables=None, inherits=None, populate_self=True, calling_uri=None)

Bases: Namespace

A Namespace specific to a Template instance.

Members

filename, module, uri

attribute mako.runtime.TemplateNamespace.filename

The path of the filesystem file used for this Namespace’s module or template.

If this is a pure module-based Namespace, this evaluates to module.__file__. If a template-based namespace, it evaluates to the original template file location.

attribute mako.runtime.TemplateNamespace.module

The Python module referenced by this Namespace.

If the namespace references a Template, then this module is the equivalent of template.module, i.e. the generated module for the template.

attribute mako.runtime.TemplateNamespace.uri

The URI for this Namespace’s template.

I.e. whatever was sent to TemplateLookup.get_template().

This is the equivalent of Template.uri.

class mako.runtime.ModuleNamespace(name, context, module, callables=None, inherits=None, populate_self=True, calling_uri=None)

Bases: Namespace

A Namespace specific to a Python module instance.

Members

filename

attribute mako.runtime.ModuleNamespace.filename

The path of the filesystem file used for this Namespace’s module or template.

If this is a pure module-based Namespace, this evaluates to module.__file__. If a template-based namespace, it evaluates to the original template file location.

function mako.runtime.supports_caller(func)

Apply a caller_stack compatibility decorator to a plain Python function.

See the example in Namespaces from Regular Python Modules.

function mako.runtime.capture(context, callable_, *args, **kwargs)

Execute the given template def, capturing the output into a buffer.

See the example in Namespaces from Regular Python Modules.