Templating & Serialization

Using Templates

To use templates your controller methods return a 2-tuple or 3-tuple:

(template_name, data)
(template_name, data, template_options)

You can omit the brackets when returning from your controller.

template_name

A string in one of the following formats:

  • package.subpackage.filename – The extension will be auto-detected if possible.
  • package.subpackage/filename.ext – Use this if the extension can not be auto-detected or if your templates folder is not a Python package.
  • /absolute/path/filename.ext
  • ./relative/filename.ext or ../relative/filename.ext

Any of the above can be prefixed with the name of an engine and a colon to override the default engine defined in your configuration.

Relative paths are relative to the working directory your web application was run within.

data
A dictionary of values to pass to the template.
template_options
A dictionary of arguments to supply to the template renderer.

An example controller method which passes the name given as an argument to the controller to a template:

def hello(self, name="world"):
    return "helloworld.templates.hello", dict(name=name)

Alternate Templating Languages

The default templating language is Genshi, however there are many others available. If you want to default all of your controller methods (that use templates) to another language, define the following in your configuration:

web.templating.engine = jinja2

You can also override the templating engine on a per-template basis by prefixing the name of the templating engine to the name of the template:

"jinja2:helloworld.templates.hello"

Returning Serialized Data

The Common Template Interface includes a number of data serialization formats out-of-the-box. The most useful ones for web development include:

bencode
The serialization format used in Bittorrent with parsers in virtually every language available. Offers a few advantages over other serialization formats. Described on Wikipedia.
json

Java Script Object Notation is best for interactive sites as JavaScript can parse the data natively.

JSON serialization is included in Python 2.6; in Python 2.5 you will need to install the simplejson module and include it in your project’s install_requires.

yaml
“Yet Another Markup Language” is a rich, human-readable, and whitespace-sensitive serialization format described here.

Others include the Python marshal and pickle formats, but those should be used with caution as they can contain executable code.

To use any of these serialization formats specify the name of the format and a single colon in your returned template name with the data to serialize as the second part of the 2-tuple. E.g.:

def index(self):
    return "json:", dict(name="world")

Unlike full templating languages, you are not restricted to dictionaries as your top-level container:

def index(self):
    return "json:", ('name', ['bill', 'bob', 'world'])

Template Globals

WebCore includes a number of useful helpers in the web and global template namespaces:

lookup
Look up the absolute path to the target template.
relative
As per lookup, but returns a relative path from the current template to the target. This is mostly just useful in Genshi templates, where relative names are required when including other templates.
web.request
Access to the WSGI request object and environment.
web.response
Access to the WSGI response object.
web.cache
Access to the Beaker cache object.
web.session
Access to the Beaker session object.
web.i18n
Internationalization hooks.
web.release
WebCore version information.

Rendering Templates Directly

Sometimes you want to render templates directly in your controller code, like when you need to use them to format an e-mail message you’re sending out. This is done using the render() function:

from web.core.templating import render

data = {'user': 'My Name', 'access_level', 'admin'}
mimetype, output = render('myproject.templates/email.html', data)

The mimetype variable contains the MIME type that resulted from the rendering of this template, which is text/html in this case. The output variable contains the actual rendered HTML as a unicode string or bytestring depending on the rendering engine used. Of course, you can also use this function to serialize data using any supported serialization format (JSON, bencode etc.).

The render() function is used internally to render templates for controllers that return a tuple, so the syntax for the template name is the same as described in the first section here. The same global variables are also available, though they will be empty if not called from within a controller (or, in other words, when the current thread is not handling a request).

Defining Your Own

To add objects to the global template namespace, append to the web.core.templating.registry dictionary:

from web.core.templating import registry

registry.append(dict(
        myglobal="foo"
    ))

To add objects to the web namespace, extend the web.core.namespace dictionary:

import web

web.core.namespace.extend(dict(
        myglobal="foo"
    ))