Recipe 14.13. Turning Data into Web Pages Through Templates
Credit: Valentino Volonghi
Problem
You need to turn some Python data into web pages based on
templates, meaning files or strings of HTML
code in which the data gets suitably inserted.
Solution
Templating with Python can be accomplished in an incredible number of
ways. but my favorite is Nevow.The Nevow web toolkit works with the Twisted networking framework to
provide excellent templating capabilities to web sites that are coded
on the basis of Twisted's powerful asynchronous
model. For example, here's one way to render a list
of dictionaries into a web page according to a template, with Nevow
and Twisted:
from twisted.application import service, internetSave this code to nsa.tac. Now, entering at a
from nevow import rend, loaders, appserver
dct = [{'name':'Mark', 'surname':'White', 'age':'45'},
{'name':'Valentino', 'surname':'Volonghi', 'age':'21'},
{'name':'Peter', 'surname':'Parker', 'age':'Unknown'},
]
class Pg(rend.Page):
docFactory = loaderslstr(""
<html><head><title>Names, Surnames and Ages</title></head>
<body>
<ul nevow:data="dct" nevow:render="sequence">
<li nevow:pattern="item" nevow:render="mapping">
<span><nevow:slot name="name"/> </span>
<span><nevow:slot name="surname"/> </span>
<span><nevow:slot name="age"/></span>
</li>
</ul>
</body>
</html>
"")
def _ _init_ _(self, dct):
self.data_dct = dct
rend.Page._ _init_ _(self)
site = appserver.NevowSite( Pg(dct) )
application = service.Application("example")
internet.TCPServer(8080, site).setServiceParent(application)
shell command prompt twistd -noy nsa.tac serves up
the data, formatted into HTML as the template specifies, as a tiny
web site. You can visit the site, at http://localhost:8080, by running a browser
on the same computer where the twistd command is
running. On the command window where twistd is
running, you'll see a lot of information, roughly
equivalent to a typical web server's log file.
Discussion
This recipe uses Twisted (http://www.twistedmatrix.com) for serving a
little web site built with Nevow (http://nevow.com/). Twisted is a large and
powerful framework for writing all kinds of Python programs that
interact with the network (including, of course, web servers). Nevow
is a web application construction kit, normally used in cooperation
with a Twisted server but usable in other ways. For example, you
could write Nevow CGI scripts that can run with any web server.
(Unfortunately, CGI scripts' performance might prove
unsatisfactory for many applications, while
Twisted's performance and scalability are
outstanding.)A vast range of choices is available for packages you can use to
perform templating with Python. You can look up some of them at
http://www.webwareforpython.org/Papers/Templates/
(which lists a dozen packages suitable for use with the Webware web
development toolkit), and specific ones at http://htmltmpl.sourceforge.net/, http://freespace.virgin.net/hamish.sanderson/htmltemplatel,
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52305,
http://www.alcyone.com/pyos/empy/,
http://www.entrian.com/PyMeld/...
and many, many more besides. I definitely
don't claim to have thoroughly tried each and every
one of these dozens of templating systems in production situations,
and I wonder whether anyone can truthfully make such a claim!
However, out of all I have tried, my favorite is
Nevow.Nevow builds web pages by working on the HTML DOM tree. Recipe 14.14 shows how you can build such
a DOM tree from within your program by using the
stan subsystem of Nevow. This recipe shows that
you can also building a DOM tree from HTML source, known as a
template. In this case, for simplicity, we
keep that template source in a string in our code, and load the DOM
for it by calling loaderslstr; more commonly,
we keep the template source in a separate l
file, and load the DOM for it by calling
loaderslfile.Examining the HTML string, you will notice it contains, besides
standard HTML tags and attributes, a few attributes and one tag from
the 'nevow:' namespace, such as
'nevow:slot', 'nevow:data' and
'nevow:render'. These additions are in accord with
the HTML standards, and also, in practice, the additions work with
all browsers. They amount to Nevow defining its own small
supplementary namespace, so that HTML templates can express
directives to Nevow for building a dynamic page from the template
together with data coming from Python code. Note that the attributes
and tags in the 'nevow:' namespace do
not remain in the HTML output from Nevow: you
can verify that, as you visit the web page served by this
recipe's script, by asking your browser to
"view source". Nevertheless,
it's important that template files are perfectly
correct HTML: this means those files can be edited with all kinds of
specialized HTML editor programs! So, like many other templating
systems, Nevow chooses to have correct HTML as its input, as well as
(of course) as its output.The 'nevow:data' directive defines the source of
the data for the page: in this case, we use the
data_dct attribute of the Pg class
instance which is building the page. The
'nevow:render' directive defines the method to use
for rendering the data into HTML strings. In this case, we use two
standard rendering methods supplied by Nevow itself:
sequence, for rendering a sequence of items, such as
a list, one after the other; and mapping, for
rendering items of a mapping, such as a dictionary, based on the
items' keys appearing as name
attributes of nevow:slot tags. More generally, we
could code our own rendering methods in any class that subclasses
rend.Page.After defining the Pg class, the recipe continues by
building a site object, then an application object, then a TCP server
on port 8080 using that site and applicationall of this
building makes up a common Twisted idiom. The source file
nsa.tac into which you save the code from this
recipe is not meant to be run with the usual
python interpreter. Rather, you should run
nsa.tac with the twistd
command that you installed as part of Twisted's own
installation procedure: twistd handles all the
startup, daemonization, and logging issues, depending on the flags we
pass to it. That is exactly why, by convention, one should normally
use file extension .tac, rather than
.py, for source files that are meant to be run
with twistd, rather than directly with
pythonto avoid any confusion.Given the experimental, toy-like nature of this recipe, you should
pass the flags -noy, to ask
twistd to run in the foreground and to
"log" information to standard
output rather than to some file. An even better idea is to read up on
twistd in the Twisted documentation, to learn
about all the options for the flags.
See Also
Twisted is at http://www.twistedmatrix.com; Nevow is at
http://nevow.com/.