Chameleon Page Templates (CPT) is a system which can generate HTML and XML.
The system is formed by the Template Attribute Language (TAL), the Expression Syntax (TALES), Intertionalization (I18N) and the Macro Expansion Template Attribute Language (METAL).
Note that this template system is based on (and closely resembles) Zope Page Templates (ZPT). If you know that system, you should be able to pick up the present system right away.
There are several template constructor classes available, one for each of the combinations text or xml, and string or file.
Most projects will benefit from the simplicity of the template loader utility:
from chameleon import PageTemplateLoader
templates = PageTemplateLoader("/some/absolute/path")
To load a template file "hello.pt" relative to the provided path, use the dictionary syntax:
template = templates['hello.pt']
The alternative is to invoke the appropriate constructor directly. Let’s try with a string input:
from chameleon import PageTemplate
template = PageTemplate("<div>Hello, $name.</div>")
All template instances are callable. Provide arguments as keywords:
>>> template(name='John')
'<div>Hello, John.</div>'
For an introduction to the language, please see the getting started section on the Zope website. Note that the expression language used in the examples there is path, not Python.
There are a number of incompatibilities and differences between CPT and ZPT. We list them here for a brief overview:
Default expression
The default expression is Python (or "python:"). The path expression syntax is not supported in the base package.Template arguments
Arguments passed by keyword to the render- or call method are inserted directly into the template execution namespace. This is different from ZPT where these are only available through the options dictionary.
Zope:
<div tal:content="options/title" />Chameleon:
<div tal:content="title" />Special symbols
The CONTEXTS symbol is not available.
The CPT system comes with a number of features and extensions that will be new to users of ZPT. Some take inspiration from Genshi.
Imports
The package introduces the import: expression which imports global names:
<div tal:define="compile import: re.compile"> ...Tuple unpacking
The tal:define and tal:repeat clauses supports tuple unpacking:
tal:define="(a, b, c) [1, 2, 3]"Extended iterable unpacking using the asterisk character is not currently supported (even for platforms that support it natively).
Dictionary lookup as fallback after attribute error
If attribute lookup (using the obj.<name> syntax) raises an AttributeError exception, a secondary lookup is attempted using dictionary lookup — obj['<name>'].
Behind the scenes, this is done by rewriting all attribute-lookups to a custom lookup call:
def lookup_attr(obj, key): try: return getattr(obj, key) except AttributeError as exc: try: get = obj.__getitem__ except AttributeError: raise exc try: return get(key) except KeyError: raise excInline expression operator
In element attributes and in the text or tail of an element, string expression interpolation is available using the ${...} syntax:
<span class="content-${item_type}"> ${title or item_id} </span>Literal content
While the tal:content and tal:repeat attributes both support the structure keyword which inserts the content as a literal (without XML-escape), an object may also provide an __html__ method to the same effect.
The result of the method will be inserted as structure.
This is particularly useful for content which is substituted using the expression operator: "${...}" since the structure keyword is not allowed here.
Switches
Two new attributes have been added: tal:switch and tal:case. A case attribute works like a condition and only allows content if the value matches that of the nearest parent switch value.
To extend the language with a new expression prefix, you need to write an expression compiler.
Let’s try and write a compiler for an expression type that will simply uppercase the supplied value.
import ast
class UppercaseExpr(object):
def __init__(self, string):
self.string = string
def __call__(self, target, engine):
uppercased = self.string.uppercase()
value = ast.Str(uppercased)
return [ast.Assign(targets=[target], value=value)]
That’s it for the compiler.
To make it available under a certain prefix, we’ll add it to the expression types dictionary.
from chameleon import PageTemplate
PageTemplate.expression_type['upper'] = UppercaseExpr
To avoid changing the existing template class, instead we could have subclassed, copied the existing expression_type dictionary and added our expression compiler there.
Adding custom expressions can be a powerful way to make the templates in your project more expressive.
This reference is split into parts that correspond to each of the main language features.
This section contains an autogenerated API reference.
The PageTemplate* constructors create template instances from source files.
Some systems have framework support for loading templates from files. The following loader class is directly compatible with the Pylons framework and may be adapted to other frameworks:
- class chameleon.PageTemplateLoader(search_path=None, **kwargs)¶