Previous Page
Next Page

23.5. Generating HTML

Python does not come with tools to generate HTML. If you want an advanced framework for structured HTML generation, I recommend Robin Friedrich's HTMLGen 2.2 (available at, but I do not cover the package in this book. To generate XHTML, you can use the approaches covered in Chapter 24.

23.5.1. Embedding

If your favorite approach is to embed Python code within HTML in the manner made popular by JSP, ASP, and PHP, one possibility is to use the Python Server Pages (PSP) supplied by Webware (mentioned in "Webware" on page 559). Another package, focused particularly on the embedding approach, is Spyce (available at For all but the simplest problems, however, development and maintenance are eased by separating logic and presentation issues through templating, covered in the next section. Both Webware and Spyce optionally support templating in lieu of embedding.

23.5.2. Templating

To generate HTML, the best approach is often templating. With templating, you start with a template, which is a text string (often read from a file, database, etc.) that is valid HTML, but includes markers, also known as placeholders, where dynamically generated text must be inserted. Your program generates the needed text and substitutes it into the template. In the simplest case, you can use markers of the form '%(name)s'. Set the dynamically generated text as the value for key 'name' in some dictionary d. The Python string formatting operator % (covered in "String Formatting" on page 193) now does all you need: if t is your template, t%d is a copy of the template with all values properly substituted.

23.5.3. The Cheetah Package

For advanced templating tasks, I recommend Cheetah (available at Cheetah interoperates particularly well with Webware and other Python server-side web frameworks, as mentioned in "Webware" on page 559. When you have Webware installed, Cheetah's template objects are Webware servlets, so you can immediately deploy them under Webware. You can also use Cheetah in many other contexts: for example, Spyce and (covered in "" on page 560) can optionally use Cheetah for templating, and TurboGears (mentioned in "Other Higher-Level-of-Abstraction Frameworks" on page 559) also relies on Cheetah. Cheetah can process HTML templates for any purpose whatsoever. In fact, Cheetah is quite suitable for templating with any kind of structured text, HTML or otherwise. The Cheetah templating language

In a Cheetah template, use $name or ${name} to request the insertion of the value of a variable named name. name can contain dots to request lookups of object attributes or dictionary keys. For example, $a.b.c requests insertion of the value of attribute c of attribute b of the variable named a. When b is a dictionary, this translates to the Python expression a.b['c']. If an object encountered during $ substitution is callable, Cheetah calls the object, without arguments, during the lookup. This high degree of polymorphism makes authoring and maintaining Cheetah templates easier for nondevelopers, as it saves them the need to learn and understand these distinctions.

A Cheetah template can contain directives, which are verbs that start with # that allow comments, file inclusion, flow control (conditionals, loops, exception handling), and more; Cheetah provides a rich templating language on top of Python. The most frequently used verbs in simple Cheetah templates are the following (similar to Python, but with $ in front of names, no trailing :, and no mandatory indents but #end clauses instead):

## comment text

Single-line comments start with two # characters (you can also use multiline comments: start with #* and end with *#); a comment that starts with doc (with no whitespace between the start-of-comment marker and the d) is used as a docstring.

#break #continue #from #import #pass

Like the Python statements with the same names.

#echo expression

Computes a Python expression (with $ in front of names) and outputs the result.

#for $ variable in $ container ... #end for

Like the Python for statement.

#include filename_expression

Reads the named file and includes its text, parsing it for Cheetah syntax.

#include raw filename_expression

Reads the named file and includes its text verbatim, without parsing.

#if...#else if...#else...#end if

Like the Python if statement (#else if and #else are optional).


Single-line if statement (else is mandatory; no else if is allowed).

#raw... #end raw

Emits some text verbatim, without checking for $name or #directive occurrences.

#repeat $ times ... #end repeat

Repeats some text $times times.

#set $ variable = expression

Assigns a value to a variable (the variable is local to this template).

#silent expression

Computes a Python expression (with $ in front of names) and hides the result.


Consumes the following newline (i.e., joins the following line onto this one).


Stops the processing of the current template file.

#while $ condition ... #end while

Like the Python while statement.

Note the differences between #echo, #silent, and $ substitution. #echo $a(2) inserts in the template's output the result of calling function a with an argument of 2. Without the #echo, $a(2) inserts the string form of a (calling a( ) without arguments, if a is callable) followed by the three characters (2). #silent $a(2) calls a with an argument of 2 and inserts nothing in the template's output.

Cheetah has many other verbs that let you control advanced functionality such as caching, filtering, setting and deleting of variables, and method definitions. A Cheetah template object is a class instance, and may use inheritance, override methods, and so on. However, for simple templates you will most often not need such powerful mechanisms. The Template class

The Cheetah.Template module supplies one class.


class Template(source=None,searchList=[],file=None)

Always call Template with named arguments (except, optionally, the first one); the number and order of parameters may change in the future, but the names are guaranteed to stay. You must pass either source or file, but not both. source is a template string. file is a file-like object open for reading, or the path to a file to open for reading.

searchList is a sequence of objects to use as top-level sources for $name insertion. The instance t of class Template is implicitly appended at the end of t's search list (e.g., $a in the template inserts the value of t.a if no other object in the search list has an attribute a or an item with a key of 'a'). searchList defaults to the empty list, so, by default, t's template expansion uses only t's attributes as variables for $ substitution.

Class Template also allows other keyword arguments, but these are the most frequently used. The instance t supplies many methods, but normally you call only str(t), which returns the string form of the expanded template. A Cheetah example

The following example uses Cheetah.Template to output HTML with dynamic content:

import Cheetah.Template import os, time, socket

tt = Cheetah.Template.Template('''
<html><head><title>Report by $USER</title></head><body>
<h1>Report on host data</h1>
<p>Report written at $asctime:<br/>
#for $hostline in $uname
#end for
''', searchList=[time, os.environ])

try: tt.uname = os.uname except AttributeError:
     tt.uname = [socket.gethostname( )]

print tt

This example instantiates and binds to name tt a Template instance, whose source is an HTML document string with some Cheetah placeholders ($USER, $asctime, $uname) and a Cheetah #for...#end for directive. The placeholder $hostline is the loop variable in the #for directive, so the template does not search the search-list objects for name 'hostline' when it expands. The example instantiates tt with a searchList argument, setting module time and dictionary os.environ as part of the search. For names that cannot be found in objects on the search list, tt's expansion looks in instance tt itself. Therefore, the example binds attribute tt.uname either to function os.uname (which returns a tuple of host description data, but exists only on certain platforms), if available, or else to a list whose only item is the hostname returned by function gethostname of module socket.

The last statement of the example is print tt. The print statement transforms its arguments into strings, as if str were called on each argument. Therefore, print tt expands tt. Some of the placeholders' expansions use dictionary lookup ($USER looks up os.environ['USER']), some perform a function call ($asctime calls time.asctime( )), and some may behave in different ways ($uname, depending on what it finds as tt.uname, calls that attributeif it is callable, as when it's os.unameor just takes it as is, when it's already a list).

One important note applies to all templating tasks, not just to Cheetah. Templates are almost invariably not the right place for program logic to reside. Don't put in your templates more logic than is strictly needed. Templating engines let you separate the task of computing results (best done in Python, outside of any template) from that of presenting the results as HTML or other kinds of structured text. Templates should deal just with presentation issues and contain as little program logic as feasible.

Previous Page
Next Page