Navigation

Real web applications require the generation of a lot of HTML pages. In the HelloWorld example from Chapter 3, you saw how to generate a string in Python code and return it from a controller action to the user’s browser to produce some visible output.

If you tried to generate a whole web application with lots of different HTML pages by generating strings in Python code, it would quickly become rather cumbersome because the Python language was not specifically designed to make it easy to generate HTML. Instead, it is often helpful to use a templating system.

Rather than writing Python code containing HTML strings, templating systems typically allow you to write HTML directly and embed Python code in your HTML when you need to do so. Since most of your template is likely to be HTML rather than Python, this is often a lot quicker. Templating languages typically also offer simple constructs for substituting variables or repeating certain sections of HTML.

As you can see, most of the template consists of HTML. Areas of the template that represent Python expressions that add to the content of the template are written inside ${}. In this example, the value of name would replace the ${name} text when the template was rendered.

Let’s see how to use this template in Pylons. Throughout this chapter, you’ll create a new Pylons application that demonstrates various features of Mako, and by the end of the chapter, you will have created a complete set of templates you can use in your own Pylons application.

Start by creating a new project. Once again, you will be asked some questions; you can choose the defaults:

Remember that the --template option in the previous command refers to project templates used to create a project directory structure for you, whereas this chapter is about view templates used to help render the HTML for a view.

Pylons projects store view templates in the project’s templates directory, but if you want to store them somewhere else, you can configure where Pylons should tell Mako to look to find your view templates by editing your project’s config/environment.py file. By default, it looks like this:

# Create the Mako TemplateLookup, with the default autoescapingconfig['pylons.app_globals'].mako_lookup=TemplateLookup(directories=paths['templates'],...)

You can replace paths['templates'] with a list of the places that Mako should search for view templates. Mako searches the directories in order.

Now that the project has been created, let’s test the greeting example you saw earlier. Save the greeting template in the TemplateDemo/templatedemo/templates/ directory as greeting.html.

You’ll also need a controller to test the template. Create a new controller in your TemplateDemo project named greeting:

$ cd TemplateDemo
$ paster controller greeting

Update the index() action of the greeting controller so that it looks like this:

The render() function is imported at the top of the controller from your project’s lib/base.py file. Within that file you’ll find the import below so the render() function in your controller is really just an alias for Pylons’ render_mako() function:

frompylons.templatingimportrender_makoasrender

You’ll look at how to use other templating languages later in the chapter. Also notice that the template paths have to start with a slash (/). This requirement was introduced in Pylons 0.9.6.

If you start the server with the pasterserve--reloaddevelopment.ini command and visit http://localhost:5000/greeting/index, you should see the HelloPylonsDeveloper! greeting in your browser (see Figure 5-1).

Although passing the name argument directly as an extra argument to render() works perfectly well, it is usually considered a better practice to assign template variables to Pylons via the template context global c, which you learned about in Chapter 3. Here is the updated controller:

Before you can use the c global, it needs importing into your controller:

frompylonsimporttmpl_contextasc

You might prefer to assign template variables to c rather than pass them in directly as arguments to render() for two reasons:

There is less chance you will accidentally assign a variable that has the same name as either one of the Pylons globals or one of the global names set up by Mako.

If a particular variable is useful in a template, there is a good chance it will be useful elsewhere in your application too. Since the c object is a Pylons global, you can also use objects assigned as attributes of c elsewhere in your application during a request.

Notice that this time the call to render() doesn’t include the c global explicitly. Pylons automatically passes this and other globals to Mako anyway, so you don’t need to do so yourself.

If you test this updated example, you will see the same output as before.

Caution

Be careful when setting c attributes that begin with an underscore (_) character. c and other global variables are really a StackedObjectProxy, which reserve the attribute names _current_obj, _push_object, and _pop_object for their internal methods.

You’ll learn about how these objects actually work under the hood in Chapter 17.

The c global is reset on each request so that you don’t need to worry about a controller still having old values set from a previous request.

One issue you learned about in Chapter 3 is that the c object doesn’t raise an AttributeError when you attempt to access an attribute that doesn’t exist and instead returns an empty string. This behavior is confusing for new Pylons developers (as well as more experienced ones), so it is recommended you disable it by specifying the strict_c option in config/environment.py. Add a new line after the Pylons configuration options:

The template context global c makes it easy to pass information around your application, but it is available only during a request. As a result, you should be very careful about creating libraries that explicitly rely on it; otherwise, your code might quickly become quite tangled.

As an example, imagine you had assigned the variables name and age to the c object and then created a function that performed some simple formatting. You might be tempted to write it like this:

Although this works perfectly well, it is bad practice—your function can be used only when Pylons is processing an HTTP request because this is the only time the c global is available. It is much better to write your function like this:

defformat_age(name,age):return"Name: %s, Age: %s"%(name,age)

and then to use it like format_age(c.name,c.age) so that the function itself does not rely on the presence of the c global. This will make it much more obvious how your code works and will make refactoring later much easier.

For the same reason, it is better to avoid using other Pylons globals such as request and response where possible. Being explicit is usually a good idea.

Now that you’ve seen how a very simple template works, it is time to look in more detail at the template syntax you’ll frequently use when working with Mako templates.

If you’d like to follow along with any of the examples in this section, create a new template called basic.html, and then create a new action in the controller to render it, because you will return to the greeting.html example later in the chapter so shouldn’t change that template now.

defbasic(self):returnrender('/basic.html')

Let’s get started. You’ve already seen basic expression substitution using the ${} construct. You can use any valid Python expression that would be suitable as a function argument within the brackets. Here is an example:

The value of 3 + 5 is: ${3 + 5}
A string representation of 3 to the power 4 is ${pow(3, 4)}

You can add comments to your templates by starting a line with the ## characters. A single # is used quite a lot in templates for CSS selectors and output for various programming languages, so it was decided ## should be used for comments rather than adopting the Python comment format of a single # character.

Make sure the ## characters are at the very start of the line with no whitespace. For example:

## This is a comment which will not be rendered
This will be rendered ## and so will this.

You can also use multiline comments using <%doc> tags. For example:

<%doc>
This is a multiline comment which will not be rendered. This style of
comment is particularly useful for documentation as well as situations where
you want to comment out a large region of your template temporarily during
testing.
</%doc>

Related to the <%doc> tag is the <%text> tag, which simply outputs verbatim whatever text is specified without treating it as Mako markup. This is very handy for documenting Mako. For example, the following:

<%text>
This is some Mako syntax which will not be executed: ${variable}
Neither will this <%doc>be treated as a comment</%doc>
</%text>

produces the unchanged output, as you would expect:

This is some Mako syntax which will not be executed: ${variable}
Neither will this <%doc>be treated as a comment</%doc>

You might need to view the HTML source code to see that this is indeed the output produced because some web browsers, including Internet Explorer, don’t handle tags containing % characters such as the <%doc> and </%doc> tags in this example.

Mako also supports the full range of control structures supported by Python, including if, elif, else, while, and for. These structures are very useful in templates. For example, to control which information is displayed, you might use an if statement:

These statements work in the same way they would in Python, including the need for a colon (:) at the end of the line. The only difference is that because templates don’t have to conform to the strict indentation rules that Python source code follows, you have to specify the point at which the control structure ends. In this case, you used an %endif line, but if you were using a while loop, for example, you would use %endwhile.

You can, of course, combine control structures too. For example, you might want to generate an HTML list from a data structure that looks like this:

Notice how the variable item specified in the for loop can still be used as an expression in the ${} construct even though it is generated in a loop and was not directly passed into the template as a namespace argument.

Also, if the bottom %endif statement was not in line with the %if statement, the template would have worked equally well. Mako doesn’t require the same indentation that Python does, although it is usually good practice to properly structure your templates anyway.

The final thing to point out about this example is that it has made extensive use of the \ character, which, when placed at the end of a line, consumes the newline character that follows it to prevent Mako from adding a line break at the end of the line.

Sometimes it is useful to be able to directly write Python code in templates. This can be done with Python blocks, although as has already been described, Python code is really best kept to the controllers where possible to provide a clean interface between your controllers and view. You can use a Python block like this:

<%
title = 'Pylons Developer'
names = [x[0] for x in c.links]
%>

Any variables you declare in Python blocks are then available to be used in control statements or in ${} constructs. For example, this code:

% for i, value in enumerate(names):
${i+1}. ${value} <br />
% endfor

produces the following output:

1. James
2. Ben
3. Philip

Any code within Python blocks must be properly indented in the same way normal source code is. The block itself can have any level of indentation. For example, although this code looks messy, it is perfectly valid:

Your title is ${title}
<%
# This block can have any indentation as long as the Python
# code within it is properly indented
if title == 'Pylons Developer':
msg = 'You must program in Python!'
else:
msg = ''
%>
An optional message: ${msg}

The code within these blocks is executed each time the template is rendered.

Because you can put Python expressions in a line containing a Mako control structure such as %if, you might be tempted to think you can write any expression after a % sign, for example, like this:

## The line below is NOT allowed:
% a = 3

Instead, any expressions should be written in blocks.

A variation of the <%%> block places the Python code within it at the top of the cached Python file Mako generates, making it very useful for import statements. Notice the ! character after the start of the first bracket in the following example:

<%!
import datetime
%>

This is called a module-level block, and when used in the context of a multithreaded Pylons application, the code it contains is executed only the first time a template is executed. Module-level blocks, as the name suggests, are good places for putting module imports, in this case, to make the datetime module available throughout the template. Module-level blocks don’t have access to the usual Mako environment and cannot be used for outputting content. We’ll discuss module-level blocks again when you learn how Mako caches templates later in the chapter.

Tip

So far, all the templates have been designed to generate HTML, but of course you can use templates to generate any sort of text-based file, be it an e-mail, a rich-text document, a configuration file, or a file format specific to your application.

The template context global c is not the only object Pylons passes to Mako for you automatically via the render() function. In addition, the following are set up by default:

tmpl_context and its alias c

This is the template context object you have already seen. Although it is usually accessed as c, you can also access it within templates as tmpl_context.

config

This is the Pylons config global described in Chapter 3.

app_globals and its alias g

This is the project application globals object you learned about in Chapter 3, usually accessed as g but available as app_globals in templates.

h

This is the project helpers module. In this case, this is templatedemo.lib.helpers, which is the place you should put all your helper functions. Again, these are described in Chapter 3.

request

This is the Pylons request object for this request.

response

This is the Pylons response object for this request.

session

This is the Pylons session object (unless sessions are removed).

translator, ungettext(), (), and N_()

These are objects to help you with internationalization. You will learn about these in Chapter 11, so you don’t need to worry about them now.

As an example, to add the current URL to the greeting.html template you have been using, you might use the h object. First import the url_for() function into the templatedemo/lib/helpers.py file with this import:

In addition to the Pylons default template variables that the Pylons render() global sets up for you, it is worth being aware that Mako sets up a number of runtime built-ins for you. I’ll mention most of these in the course of this chapter, but for full information about each, you should consult the Mako documentation at http://www.makotemplates.org/docs/documentation.html#runtime_builtins.

Here’s a quick summary so that you can make sure you don’t accidentally use any of these as names of your own variables in templates:

context

This context is the central object that is created when a template is first executed and is responsible for handling all communication with the outside world. It includes the output buffer and a dictionary of the variables that can be freely referenced within a template; this includes the other Mako runtime built-ins, the Pylons default variables, and any extra variables passed by the extra_variables argument to render(). As such, the context object is very important. You can learn more about it at http://www.makotemplates.org/docs/documentation.html#runtime.

local, self, parent, and next

These are all namespaces and have particular meanings in the context of template inheritance chains. You’ll look at these later in the chapter.

capture

This is a function that calls a given def and captures its resulting content into a string, which is returned. A def is Mako terminology for a reusable block of template code wrapped in a <%def> tag that behaves a bit like a function in Python. You’ll learn about defs and the capture() function later in the chapter.

This is an instance of mako.runtime.Undefined that raises an exception when its __str__() method is called. It is used when you use a variable in a template without assigning it a value. If you see an UNDEFINED, it is likely that you mistyped a variable name or forgot to pass a particular variable to a template.

<html>
<body>
<p>Here is an example:</p>
<p>
The key is <tt>all</tt>, the value is &lt;built-in function all&gt;. <br />
The key is <tt>help</tt>, the value is Type help() for interactive help, or help(object) for help about object.. <br />
The key is <tt>vars</tt>, the value is &lt;built-in function vars&gt;. <br />
The key is <tt>SyntaxError</tt>, the value is &lt;type 'exceptions.SyntaxError'&gt;. <br />
The key is <tt>session</tt>, the value is {}. <br />
The key is <tt>unicode</tt>, the value is &lt;type 'unicode'&gt;. <br />
The key is <tt>sorted</tt>, the value is &lt;built-in function sorted&gt;. <br />
...

The two important things to realize are that writing output with context.write() has the same effect as using ${} and that any variables that can be used in a template can be accessed with context.get().

The greeting example you have been using so far is rather artificial because you could have just put your name directly into the template. Real web applications respond to data from various sources, so let’s make our example slightly more realistic by retrieving the name of the visitor from the query string on each request. If no query string is present, you’ll just use Visitor as the name.

This is a much more realistic example. Here the controller does some processing based on some logic and then passes relevant information to the template to display. In this setup, the template represents a view of the data in the Model View Controller architecture, and in line with this architecture, it is generally considered best practice to keep logic code in your controller and use Python only in your template to assist with rendering the information passed by the controller.

Some templating languages take the separation of logic code and view code to extremes and actively prohibit any sort of data processing in the template. Although this might be good practice, it can be sometimes be terribly frustrating when you want to do something simple if the templating language prevents you from doing it. Mako takes the view that the developer knows best and therefore provides some powerful templating tools and the ability to embed Python code in the template. It is then up to you as a developer to decide how much to use the tools Mako provides.

Here is the same example written slightly differently just to demonstrate that you can put simple logic in templates if you really need to do so. Here’s the action:

One point to watch out for when you are using any data from the Web in a template is that a malicious user might put HTML characters in the data. If, for example, you visit the URL http://localhost:5000/greeting/index?name=Ja%3Cb%3Em%3C%2Fb%3Ees, the value of request.params['name'] would be Ja<b>m</b>es, and if Mako didn’t apply any special escaping, this value would be rendered, resulting in the m being made bold in the HTML rendered by the browser.

In itself this might not seem like a big problem, but actually it opens your web application up to so-called cross-site scripting (XSS) attacks. For example, a malicious user could insert JavaScript into your page to replace some of your own content to trick the user of the page into giving away information or visiting a site they didn’t intend to because they thought the content on the page was generated by you.

This is a real risk for many websites today, so it is well worth being aware of. Pylons protects you from making this mistake by automatically escaping all values rendered by Mako. If you look at your project’s config/environment.py again, you will see that the full configuration for Mako looks like this:

The last argument, default_filters, means that all output is filtered through the webhelpers.html.escape function, which automatically applies HTML escaping to make the content safe.

Of course, sometimes you want to pass data to Mako and have it treated as HTML. To do this, you have to wrap the content in a webhelpers.html.literal() object. A literal is a special type derived from Python’s built-in unicode type. When the escape() function finds a literal, it doesn’t escape it.

To demonstrate these features, update the greeting.html template so it looks like this:

Rather than using the webhelpers.html.literal object directly, most Pylons developers prefer to import it into their project’s lib/helpers.py file so that it can be accessed as h.literal in controllers.

Update the lib/helpers.py file to include this import:

"""Helper functionsConsists of functions to typically be used within templates, but alsoavailable to Controllers. This module is available to both as 'h'."""# Import helpers as desired, or define your own, ie:# from webhelpers.html.tags import checkbox, passwordfromwebhelpers.htmlimportliteral

Now import the helpers module into your controller as h by adding this at the top of controllers/greeting.py:

importtemplatedemo.lib.helpersash

Finally, change the index() action of the controller to look like this:

As of WebHelpers 0.6, all the HTML helper functions automatically return literal() objects, described earlier, so that their return values are treated as HTML. If you have created your own helper functions for a previous version of Pylons and try to use them with a Pylons 0.9.7 application, you will probably be surprised to find that all the output is escaped. You can solve this problem by modifying the helper functions to return an HTML literal object instead of a Python unicode or str object.

When writing or upgrading helper functions to use HTML literals, you should be careful that you don’t accidentally introduce security holes. For example, consider this function:

You have introduced a security hole because the Ja<b>m</b>es string is concatenated with the <em> and </em> strings in the emphasize() helper, and the whole string <em>Ja<b>m</b>es</em> is marked as a literal. The <b> and </b> tags now pass through the escape() function and through to the HTML document. This is not the behavior you want. Instead, the emphasize() function should be written like the following so the value itself isn’t accidentally marked as an HTML literal:

defemphasize(value):returnliteral('<em>')+value+literal('</em>')

To avoid the problem, WebHelpers 0.6 introduced an HTML object that can be used for generating HTML fragments in a safe way. Here is the emphasize helper written using the HTML object:

defemphasize(value):returnHTML.em(value)

You can also nest HTML objects; the following would also wrap the value in a <span> tag:

defemphasize(value):returnHTML.span(HTML.em(value))

You can also add HTML attributes as keyword arguments to HTML. Where an attribute name is a reserved word in Python, you should add _ to the end of the argument. For example, here is a <span> tag with an id attribute of first and a class attribute of highlight:

Calling emphasize('Ja<b>m</b>es') would return a literal object representing the Unicode string u'<spanid="first"class="highlight"><em>Ja&lt;m&gt;es</em></span>' with the HTML characters from the argument correctly escaped.

The escape() function set up as a default filter in config/environment.py is applied to all Mako output, but you can also apply filters to specific Mako output by using Mako’s | operator within a ${} expression in a template.

This produces HTML escaping, provided by cgi.escape(string,True). Note that this is not the same as the helpers module object h, which is also available in templates. Mako knows when you are using h as a filter and when it is supposed to refer to your project’s helpers module.

x

This produces XML escaping.

trim

This produces whitespace trimming, provided by string.strip().

entity

This produces HTML entity references for applicable strings, derived from the htmlentitydefs module in the standard library.

unicode

This produces a Python Unicode string (this function is applied by default).

decode.<someencoding>

This decodes input into a Python Unicode string with the specified encoding.

n

This disables all default filtering; only filters specified in the local expression tag will be applied.

You can also use the escape function because Mako is configured by the following line to automatically import into all templates:

imports=['from webhelpers.html import escape'],

Here’s an example of how filtering works:

${ c.test | trim,entity }

If c.test had the value u"Itwillcost£5", the spaces would be stripped by trim, the £ sign would be converted to the HTML entity &pound;, and the output would simply be Itwillcost&pound;5.

If you have an HTML string that is not wrapped in literal() but that shouldn’t be escaped, you can disable the default escape filter with n. For example, if c.test contained the Unicode string u'<b>Hello</b>', you could have this passed through unescaped like this:

The ability to substitute variables, control program flow, and execute small snippets of Python are all very useful, but what gives templates their real value is the ability to define template blocks and call them from other templates to produce complex page layouts with as little duplication of effort as possible. In the following sections, you’ll learn about some of the ways Mako allows you to do this.

A def block is rather like a Python function in that each def block has a name, can accept arguments, and can be called. As an example, let’s update the list-generating code you used earlier to be a reusable def block:

There’s quite a lot going on in this example, so let’s take it piece by piece. You can see you have two functions. The first is called navigation_links() and takes two arguments: selected is the label of the currently selected navigation link, and links is the list of links.

Within the navigation_links() function, there is another function called link() that generates an HTML link if a URL is associated with the navigation link.

Finally, there is a definition of the links defined in Python block at the top and some code to call the navigation_links() function at the bottom. Save this template code as navigation.html. You can then test it by adding a new action to the controller:

The extra whitespace is because you have concentrated on making your template look neat rather than concentrating on the HTML output. To remove all the whitespace, your HTML statements would have to begin at the start of the line because by default Mako does not strip out whitespace.

Notice that you have controlled some of the line endings, though. Leaving a trailing \ character at the end of the line tells Mako not to insert a line end character, so you can see there is no line end after the </b> tag even though there is some whitespace, which comes from the following line in the template before the </li> tag.

Defs in Mako behave very similarly to functions in Python and have access to their parent scope. This means you would be able to use the selected and links variables within the link() def.

You might also have noticed that the navigation_links() function was called before its definition. All top-level functions are loaded into memory before the main body of the template is rendered, so this is perfectly acceptable too.

The link() def is called from within navigation_links(). Just like in Python, the link() function would not be callable from outside navigation_links() because it is local to the navigation_links() scope.

It can sometimes be difficult to remember exactly what rules apply to defs, particularly when you get involved with more complex examples such as the inheritance chains you’ll see later in the chapter. Luckily, there is an easy way to find out what is going on behind the scenes.

Mako works by compiling the templates you write into ordinary Python code the very first time it is executed or any time it is executed after it has been changed. Any subsequent times the template is rendered, the Python file is simply executed, and the output is returned.

Mako caches these templates according to the value of the cache_dir variable in your project’s development.ini file. By default, this is set to the value %(here)s/data. The %(here)s value gets replaced with the location of the development.ini file, so Mako will cache the files in your project’s data/templates directory by default.

Let’s have a look at the cached template for the navigation.html template you’ve just created. Its cached counterpart is in TemplateDemo/data/templates/navigation.html.py. Let’s look at each part of the file in turn starting with the top:

Here Mako defines various variables related to your template. You can see the import of the escape function that was specified as an argument to the TemplateLookup in your project’s config/environment.py file. If you had defined any module-level blocks, their contents would also be placed in this part of the cache.

Next is the render_body() function that represents the main body of each template:

In this case, you can see the items list being defined and the call to navigation_links() being made. This in turn calls the render_navigation_links() function, which is rather long, so I won’t repeat it here.

Each part of the cached template is simply normal Python code even though some of the variables start with __M_ to avoid the risk of naming conflicts. You can also see the escape() function being used, so it is clear which variables are escaped and which aren’t.

If you look carefully at the render_body() method, you’ll notice context.caller_stack.push_frame() is called at the start of the rendering and context.caller_stack.pop_frame() is called at the end. These two calls help Mako keep track of where it is in the inheritance chains you will learn about later in the chapter.

Although you would never use the cached Mako templates directly, it is helpful to realize they are there. If you ever run into difficulties, looking at the cached version can sometimes shed light on a problem.

Something to be aware of when calling defs is that their output is rendered straight to the context output buffer—it isn’t actually returned.

If you look at the cached template example again, it should be clear why. Each line of source template is wrapped in an __M_writer() call, which has the effect of calling context.write(). If you want to actually capture the output of a def to a variable rather than to the output buffer, you have to use capture().

Running this example produces the following HTML source (although you won’t see the line breaks in a web browser):

3
The result of 1 + 2 is None

What happens here is that the output of the add() def is written to the output buffer, not captured and passed to the display() def. The add() def actually returns None, which is the value returned by ordinary Python functions if no value is explicitly returned. Instead, you want to capture the output from the add() def. You can do this by modifying the line that calls it to look like this:

${display(1, 2, capture(add, 1, 2))}

The capture function is one of Mako’s built-in template variables. It takes the def to capture as the first argument and the values to pass to the def as the subsequent arguments. The new output is as follows:

The result of 1 + 2 is 3

If you are interested, you can read more about Mako’s output buffering in the Mako documentation.

In a real web application, it is likely that most of the pages will need navigation links, so it would be useful if you could import the navigation_links() function you have just created into other templates. You can do this using the <%namespace> tag.

Update the greeting.html template so that it imports and uses the navigation_links() function from the template you just created.

You can also just use import="*" to import everything from another template or import="component1,component2" to specify specific components you want to import. The names imported by the import attribute take precedence over any names that exist within the current context.

Namespaces can also import regular Python functions from modules as long as they accept an argument named context as their first argument. As an example, a module file my/module.py might contain the following callable:

defwrite_greeting(context):context.write("hello world")

A template can then use this module as follows:

<%namespace name="my" module="my.module" />
${my.write_greeting()}

Note that the context argument is not needed in the call. When Mako generates the cached Python version, it creates a locally scoped callable, which is responsible for passing the context object in for you.

There is one other important <%def> you will need to know about called the body() def. The body() def represents the whole of the body of the template, that is, any template code not wrapped in its own def. For example, if you had a template that looked like this, the 12:00pm line would be in the body() def.

<%def name="test()">Hello World!</%def>
12:00pm

You can see this in action by using this template in another one. Imagine the previous template was saved as greeting_and_time.html. You could create another template like this to use its functionality under the namespace other:

<%namespace name="other" file="/greeting_and_time.html" />
The greeting is ${other.test()}
The time is ${other.body()}

Notice how the calling body method is effectively just like a normal <%def> but without the opening and closing <%def> tags needing to be specified. The output is as you would expect:

The greeting is Hello World!
The time is 12:00pm

Being able to access the body of a template is really useful when you are using template chains in an inheritance structure. Let’s look at this in the next section.

The real value of templating languages isn’t so much that they help you mix and match Python and plain text in a more efficient manner but that so much of their functionality can be reused effectively in other pages. You’ve already seen how you can create reusable components using <%def> blocks and then import them into other templates using the <%namespace> tag, but Mako also provides facilities to enable you to structure your templates so that derived templates can inherit functionality from a base template.

Using a template chain in Mako is best explained with an example. The following is a base template named base.html, which defines some HTML and a footer but also has two defs, self.title() and self.body(). Save this template as base.html in templatedemo/templates:

Let’s modify the greeting example to use this template. Let’s ignore the namespace code you added earlier in the chapter for the minute and just concentrate on inheriting the base template. Here’s how it looks:

Let’s think about what is going on to produce this HTML. Because greeting.html inherits from the base.html control for rendering passes directly to the base.htmlbody() def. The <html> line is rendered first, followed by all the other characters until ${self.title()} is called.

In the context of rendering a normal template, self would refer to the template itself, but in the context of an inheritance chain like this one, self always refers to the template at the bottom of the inheritance chain, which is always the template that was originally specified in the call to render(), in this case, greeting.html. This means that although you are rendering the base.htmlbody() def, ${self.title()} refers to the title() def in greeting.html. This renders the Greeting text, which appears in the page title.

Once the title is rendered, control passes back to the base.html template, and more HTML is rendered until ${self.body()} is reached. Once again, self refers to greeting.html, so the body() def of greeting.html is rendered. Finally, control passes back to base.html to render the footer, and the whole page is rendered.

As you can imagine, being able to structure your templates like this is really useful because it means you can now create multiple templates based on base.html without having to duplicate its content in each child template. By using defs in the way you used title(), you can create regions that can be replaced in child templates. These don’t just have to contain static text; they can also contain navigation elements, CSS, JavaScript, section headings, or any other content you like. When you start the SimpleSite tutorial, you’ll use inheritance chains to create a full-featured site.

Caution

If you are following the Mako documentation, you should be aware that Mako describes the template at the top of the chain (base.html in our example) as being the bottom-most template and the template at the bottom as being the top-most template, so you need to be aware of the slightly confusing terminology.

In the previous example, you used the self namespace to effectively mean “use the def from the template furthest down the inheritance chain.” Mako also provides two related namespaces called next and parent, which are especially useful if you have more than two templates involved in an inheritance chain.

Imagine the greeting template you’ve been using is actually part of the user administration section of a site. This site might also need some section links to allow the user to navigate around the section, but if these links were put in the base.html template, they would appear on all pages in the site, not just in the user administration section. You could put the links in the greeting.html template, but then you would also have to duplicate them in other templates in the same section. You could do this by keeping the links in a namespace and simply calling the def in each template rather than duplicating the code each time, but Mako provides a better solution.

It turns out that you aren’t limited to two templates in an inheritance chain; you can have as many templates as you like. Rather than inheriting the greeting.html template from the base.html template, let’s create a new template specifically for the user administration section; call it section.html, and save this file in the templatedemo/templates directory with the following content (there is a deliberate mistake in this template, though, so you might want to read on first):

Notice that this template inherits from base.html and that you are still using the navigation.html template you created earlier to do the hard work of creating the links.

For the greeting.html template to use this template, you need to change its <%inherit> tag to look like this:

<%inherit file="/section.html"/>\

If you refresh the browser, you will see that the content hasn’t changed! This might surprise you, so let’s think about what’s happened. You call render() to render greeting.html, and control is passed to the section.htmlbody() def, but this template is inherited from base.html, so control passes to the base.htmlbody() def. Once again, HTML is rendered until ${self.title()} is reached. Remember that self refers to the last template in the chain, in this case, greeting.html, so it is the greeting.htmltitle() def and body() def that are rendered, not the ones in section.html.

To solve this problem, you need to use Mako’s next namespace. next is similar to self but refers to the next template in the chain, not the last one. To use next, you’ll need to change all the references to ${self.title()} and ${self.body()} in base.html and section.html to use ${next.title()} and ${next.body()}, respectively.

Once you’ve updated the templates, they behave as you expect. When ${next.title()} is reached, the title() def from section.html is rendered. Control is passed back to base.html until ${next.body()} is reached; then the body() def of section.html is rendered, producing the navigation links. When ${nextbody()} is reached in section.html, the body() def from greeting is rendered. When it is finished, control passes back to section.html and then back to base.html to finish off the rendering.

Figure 5-2 shows the result.

Figure 5-2. Greeting produced with a template inheritance chain

If the section.html template didn’t have a title() def, the call to ${next.title()} in base.html would have rendered the title() def in greeting.html instead.

Middle templates such as section.html are normally used for sections of the site in this way with base templates such as base.html containing content that applies to every page and child templates such as greeting.html containing only page-specific information. Of course, if you have a large site, it might make sense to have more than one middle template so that you can implement subsections or different page layouts within a section. The inheritance technique is very flexible.

In the same way that the next namespace allows you to refer to a def in the namespace of the child template immediately below it, Mako also provides a parent namespace that allows a child template to refer to a def in the parent template immediately above it. This is useful if you want a child template to be able to control where in a parent template its content is inserted.

Note

Using the parent namespace might remind you of using super in a derived class to access a method in a base class in a normal Python inheritance structure. The two are similar, but in Python there is no equivalent to the next namespace; that is, you cannot access a child method from a parent class.

Let’s change the way the title() def works so that greeting.html can decide whether to include the content from the section.htmlbody() def. The first thing you need to do is change base.html so that it calls ${self.title()} rather than ${next.title()}. This means that when the title is rendered, control for rendering the def will pass to greeting.html, bypassing section.html.

<html>
<head>
<title>${self.title()}</title>
...

If you tested the example, you will see that the page title now displays Greetings again. Now let’s change greeting.html so that the title also includes the section title. You’d like the title to read “User Administration > Greetings.” Update the title() def in greeting.html to look like this:

<%def name="title()">${parent.title()} &gt; Greetings</%def>

Now when control for rendering the title() def passes from base.html to greeting.html, the greeting.htmltitle() def calls its parent template title() def where the UserAdministration string is rendered as expected.

Using the parent namespace in this way is particularly useful when working with sections containing JavaScript or CSS, because you’ll often find that it is useful to be able to control whether the JavaScript and CSS for the child template is rendered before or after that of the parent.

In summary, the rule of thumb is that if the base template should have control of where the child content should be placed, use next. If the child template needs control of where its own content is placed, use parent.

Now that you have a good idea of how to use Mako templates within Pylons, you can turn your attention to how Pylons links the render() function you call to the template engine code as well as how it adds default variables. Once you understand the basic principles, you’ll look at how to use the alternative template languages Pylons supports, as well as how to add support for your own template languages.

If you intend to use only Mako in your Pylons applications and are not interested in understanding what is going on behind the scenes, you might prefer to jump ahead to the next chapter to begin learning about forms.

Let’s start by looking at the definition of the pylons.templating.render_mako() function that you imported as render() in the greeting controller. It looks something like this:

The first thing you should notice is that the function supports caching with a call to cached_template(). You’ll look at the caching options in a minute, but let’s start by looking at what happens in the render_template() function.

First, a dictionary is set up called globs, which contains any values you specified in the extra_vars keyword. This dictionary is then updated with all the Pylons globals that I described earlier in the “Default Pylons Template Variables” section. These are returned automatically by the pylons_globals() function.

One of the globals returned is the app_globals object, which you’ll remember from Chapter 3, is an instance of your project’s templatedemo.lib.app_globals.Globals class. This class has an attribute called mako_lookup, but if you look at your project’s templatedemo/lib/app_globals.py file, you’ll see that mako_lookup isn’t defined there. It is actually added dynamically when the application is first loaded by the configuration code in config/environment.py. Here are the relevant lines. You’ll recall that you looked at the options to TemplateLookup earlier in the chapter:

Once the template has been returned, the final act of the render_template() function is to return the rendered template, passing in the variables you have specified as keyword arguments.

As you can see, although it takes a careful look through the code, the templating setup is actually easy to understand. This is typical of the way most of Pylons works. With a little digging through the source code, you can usually work out what is going on and customize the behavior you want in your own Pylons application.

Sometimes it is useful to be able to cache template calls to speed up performance. As you’ve seen, the render_mako() function has a number of options to support this, each of which defaults to None if it is not specified:

cache_key

This is the key to cache this copy of the template under.

cache_type

This is the cache type. Valid options are dbm, file, memory, database, or memcached.

cache_expire

This is the time in seconds to cache this template with this cache_key. Or use never to designate that the cache should never expire.

These options are then used, along with the template name, to cache the result of the call to the render_template() function I’ve just described. The caching functionality comes from the Beaker package and is described in detail at http://docs.pylonshq.com/caching/. Pylons also supports sophisticated caching options to cache other types of data and supports other types of caching, but these are beyond the scope of the book; have a look at the previously mentioned link for the full information.

To test the caching, let’s modify the base.html template to add the current date and time to the footer of every page. Change the template to look like this:

Now the first time you visit the page, the current time will be displayed, but every subsequent visit will result in the page being returned from the cache until five seconds have passed. After five seconds, a new page will be rendered with a new date and time, but once again, this new page will be returned from the cache only after five seconds have passed.

If no cache_type is specified, the default used is dbm, which stores the cached pages in a simple database within your cache directory. Have a look at data/cache, and you will see the data folders present where the cache has been stored on disk. If you don’t specify a cache_key, the key default is used. Specifying never as the cache_expire argument will mean the cache won’t expire. Obviously, though, if you are using the memory cache type, restarting the server will cause the cache to be emptied.

This is an XML templating language designed to make generating valid XHTML and XML straightforward. Genshi is very popular with Pylons programmers and is used as the default templating language in TurboGears.

All three template engines are very different, but they each have one thing in common: they are all written as improvements to existing template engines. Genshi is the formal successor of Kid, Mako replaced Myghty, and Jinja was inspired by Django templates. This means all three are well-thought-out and production-ready template systems. They all use Unicode internally and have an API that is easy to use with Pylons.

Deciding between them is really a matter of preference. If you are primarily writing an application that outputs XML or XHTML, then you might find Genshi useful because it guarantees that your output is well formed. On the other hand, Mako and Jinja are much faster than Genshi and allow much more flexibility in the output they produce. Genshi requires a completely different syntax for text-based output, but if you are writing a predominantly XHTML-based application, this may not be a problem. All three handle the escaping of data correctly with Pylons thanks to the use of the HTML literals I described earlier.

If you are fairly new to templating languages and are trying to pick a templating language to use with Pylons, Mako is a good choice, and that is why it was chosen to be the default templating language for Pylons. Of course, Pylons doesn’t restrict you to using a single templating language. If you think it would be helpful in your application, you can use multiple templating languages at the same time. You’ll see how to do this later in the chapter.

To use an alternative template language, you will need to first install it:

$ easy_install Genshi
$ easy_install Jinja

If you want to use one of the alternative templating languages in your project but don’t need Mako support, the easiest thing to do is to specify the templating language you want when you run the pastercreate command. For example, to get a Genshi project, you might do this, specifying genshi when prompted:

Then in your lib/base.py file, rather than importing the render_mako() function, you would import render_genshi() like this:

frompylons.templatingimportrender_genshiasrender

Genshi doesn’t generate output directly; instead, it generates a stream of nodes. Genshi streams can be serialized using one of four methods: xml, xhtml, html, or text. The render_genshi() function takes an extra argument named method that you can use to specify the output method. It defaults to xhtml, but you can choose a different value if you want a different type of output.

You can follow a similar process to set up a project to work exclusively with Jinja, specifying jinja when prompted by pastercreate and using the render_jinja() function in your controllers.

As was mentioned a moment ago, nothing is stopping you from using more than one templating language in your Pylons application. This requires a little more work because you must add the template lookup code to config/environment.py yourself. This isn’t difficult, though.

Let’s modify the TemplateDemo example you’ve been using to add Jinja support too. First install Jinja:

$ easy_install "Jinja==1.2"

Now open config/environment.py, and change the end of the load_environment() function to look like this:

One of the great benefits of choosing a web framework based on Python is the sheer breadth of software available for you to use, including a large number of templating languages. If you’ve come from a background of Cheetah, Tal, Stan, Myghty, Kid, Breve, or any of the other templating languages available, you can easily integrate them into your Pylons application. The integration requires two steps:

Create a template lookup object attached to the app_globals object in config/environment.py.

Create a render function, using the pylons_globals() and cached_template() functions if necessary, and use the template lookup attached to app_globals to render the template.

Use the render_mako() function and config/environment.py listings from earlier in this chapter as a basis for your own code. If you need a further example, the Pylons documentation includes an example of how to integrate Kid via a custom render() function. You can read it at http://docs.pylonshq.com/views/#custom-render-functions.

This chapter was a fairly in-depth guide to the main aspects of templating in Pylons. You learned how to pass variables to templates via the template context variable c, how to avoid security problems through automatic escaping, and how to use HTML literals. You also learned the main features of Mako, from its template syntax to its inheritance chains, and you saw how to use its next and parent namespaces. You also learned all about what goes on behind the scenes to make templating in Pylons work from the Mako cache to the render() function setup.

There has clearly been a lot to take in. Don’t worry if you didn’t understand every detail on the first read. You’ll be using Mako templates throughout the book, particularly in the SimpleSite tutorial chapters, so you’ll get plenty of practice working with them to build real applications.

Next up you will learn how to create forms with Pylons, how to validate their content, and how to present error messages to the user if they enter invalid data.