Note: If you are not familiar with the ZPT language, you should read the tutorial in section 5.3.3 before continuing in this section. See the links in the previous section for documentation on the other template engines.
By default, templates are loaded from the directory where the renderer module was imported from. In addition, the templates from each of the parent renderer class modules are also loaded. This makes it very easy to extend a renderer and add just a few new templates to support the additions that were made.
The template files in the module directories can have three different forms. The first is HTML. HTML templates must have an extension of ‘.htm’ or ‘.html’. These templates are compiled using SimpleTAL’s HTML compiler. XML templates, the second form of template, uses SimpleTAL’s XML compiler, so they must be well-formed XML fragments. XML templates must have the file extension ‘.xml’, ‘.xhtml’, or ‘.xhtm’. In any case, the basename of the template file is used as the key to store the template in the renderer. Keep in mind that the names of the keys in the renderer correspond to the node names in the document object.
The extensions used for all templating engines are shown in the table below.
Engine |
Extension |
Output Type |
ZPT |
.html, .htm, .zpt |
HTML |
Jinja2 |
.jinja2 |
Any |
.xhtml, .xhtm, .xml |
XML/XHTML |
|
Python string formatting |
.pyt |
Any |
Python string templates |
.st |
Any |
Kid |
.kid |
XML/XHTML |
Cheetah |
.che |
XML/XHTML |
Genshi |
.gen |
HTML |
The file listing below is an example of a directory of template files. In this case the templates correspond to nodes in the document created by the description environment, the tabular environment, \textbf, and \textit.
description.xml tabular.xml textbf.html textit.html
Since there are a lot of templates that are merely one line, it would be inconvenient to have to create a new file for each template. In cases like this, you can use the ‘.zpts’ extension for collections of ZPT templates, or the ‘.jinja2s’ extension for collections of Jinja2 templates, or more generally ‘.pts’ for collections of various template types. Files with this extension have multiple templates in them. Each template is separated from the next by the template metadata which includes things like the name of the template, the type (xml, html, or text), and can also alias template names to another template in the renderer. The following metadata names are currently supported.
Name |
Purpose |
engine |
the name of the templating engine to use. At the time of this writing, the value could be zpt, tal (same as zpt), html (ZPT HTML template), xml (ZPT XML template), jinja2, python (Python formatted string), string (Python string template), kid, cheetah, or genshi. |
name |
the name or names of the template that is to follow. This name is used as the key in the renderer, and also corresponds to the node name that will be rendered by the template. If more than one name is desired, they are simply separated by spaces. |
type |
the type of the template: xml, html, or text. XML templates must contain a well-formed XML fragment. HTML templates are more forgiving, but do not support all features of ZPT (see the SimpleTAL documentation). |
alias |
specifies the name of another template that the given names should be aliased to. This allows you to simply reference another template to use rather than redefining one. For example, you might create a new section heading called \introduction that should render the same way as \section. In this case, you would set the name to “introduction” and the alias to “section”. |
There are also some defaults that you can set at the top of the file that get applied to the entire file unles overridden by the meta-data on a particular template.
Name |
Purpose |
default-engine |
the name of the engine to use for all templates in the file. |
default-type |
the default template type for all templates in the file. |
The code sample below shows the basic format of a zpts file.
name: textbf bfseries <b tal:content="self">bold content</b> name: textit <i tal:content="self">italic content</i> name: introduction introduction* alias: section name: description type: xml <dl> <metal:block tal:repeat="item self"> <dt tal:content="item/attributes/term">definition term</dt> <dd tal:content="item">definition content</dd> </metal:block> </dl>
The code above is a zpts file that contains four templates. Each template begins when a line starts with “name:”. Other directives have the same format (i.e. the name of the directive followed by a colon) and must immediately follow the name directive. The first template definition actually applies to two types of nodes textbf and bfseries . You can specify ony number of names on the name line. The third template isn’t a template at all; it is an alias. When an alias is specified, the name (or names) given use the same template as the one specified in the alias directive. Notice also that starred versions of a macro can be specified separately. This means that they can use a different template than the un-starred versions of the command. The last template is just a simple XML formatted template. By default, templates in a zpts file use the HTML compiler in SimpleTAL. You can specify that a template is an XML template by using the type directive.
Here is an example of using various templates engines in a single file.
name: equation engine: jinja2 <div class="equation" id="{{ obj.id }}"> <span class="equation_label">{{ obj.ref }}</span> {{ obj }} </div> name: textbf engine: python <b>%(self)s</b> name: textit engine: string <i>${self}</i> name: textsc engine: cheetah <span class="textsc">${here}</span> name: textrm engine: kid <span class="textrm" py:content="XML(unicode(here))">normal text</span> name: textup engine: genshi <span class="textup" py:content="markup(here)">upcase text</span>
There are several variables inserted into the template namespace. Here is a list of the variables and the templates that support them.
Object |
ZPT/Python Formats/String Template |
Jinja2 |
Cheetah |
Kid/Genshi |
document node |
self or here |
obj or here |
here |
here |
parent node |
container |
container |
container |
container |
document config |
config |
config |
config |
config |
template instance |
template |
|||
renderer instance |
templates |
templates |
templates |
templates |
You’ll notice that Kid and Genshi templates require some extra processing of the variables in order to get the proper markup. By default, these templates escape characters like <, >, and &. In order to get HTML/XML markup from the variables you must wrap them in the code shown in the example above. Hopefully, this limitation will be removed in the future.
When using Jinja2 templates, the default configuration trims white spaces before and after template tags (see trim_blocks and lstrip_blocks in Jinja2’s documentation). Also, when developing Jinja2 templates, inserting {{ debug() }} will launch a python debugger session to allow inspection of the context variable during rendering.
It is possible to override the templates located in a renderer’s directory with templates defined elsewhere. This is done using the *TEMPLATES environment variable. The “*” in the name *TEMPLATES is a wildcard and must be replaced by the name of the renderer. For example, if you are using the XHTML renderer, the environment variable would be XHTMLTEMPLATES. For the PageTemplate renderer, the environment variable would be PAGETEMPLATETEMPLATES.
The format of this variable is the same as that of the PATH environment variable which means that you can put multiple directory names in this variable. In addition, the environment variables for each of the parent renderers is also used, so that you can use multiple layers of template directories.
You can actually create an entire renderer just using overrides and the PT renderer. Since the PT renderer doesn’t actually define any templates, it is just a framework for defining other XML/HTML renderers, you can simply load the PT renderer and set the PAGETEMPLATETEMPLATES environment variable to the locations of your templates. This method of creating renderers will work for any XML/HTML that doesn’t require any special post-processing.