Mako for people in a hurry
This is one of a set of quick guides for getting started with the different components of Pylons.
Introduction
The Mako template library deals with the 'view' portion of the Pylons framework. It generates (X)HTML code, CSS and javascript that is sent to the browser.
Beware static vs. dynamic
Templates to generate dynamic web content are stored in myapp/templates, static files are stored in myapp/public.
Both are served from the server root, if there is a name conflict the static files will be served in preference!
Install and setup Mako
In case Mako is not already installed, at the command-line type,
Making templates unicode safe
Edit myapp/config/environment.py and add these lines just after tmpl_options = {} is declared,
1
2
3 | tmpl_options['mako.input_encoding'] = 'UTF-8'
tmpl_options['mako.output_encoding'] = 'UTF-8'
tmpl_options['mako.default_filters'] = ['decode.utf8']
|
then change the final return statement in the same file so that it reads,
1
2 | return pylons.config.Config(tmpl_options, map, paths,
request_settings = dict(charset = 'utf-8', error = 'replace'))
|
Also make sure that all templates you create begin with the line,
Making a template hierarchy
Create a base template
In myapp/templates create a file named base.mako and enter the following,
1
2
3
4
5
6
7
8
9
10
11 | # -*- coding: utf-8 -*-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
${self.head_tags()}
</head>
<body>
${self.body()}
</body>
</html>
|
We can use a base template such as the very basic one above for all pages rendered by Mako. This is useful for giving a consistent look to the application.
- Expressions wrapped in ${...} are evaluated by Mako and returned as text
- ${ and } may span several lines but the closing brace should not be on a line by itself (or Mako throws an error)
- Functions that are part of the self namespace are defined in the Mako templates
Create child templates
Create another file in myapp/templates called my_action.mako and enter the following,
1
2
3
4
5
6
7
8
9
10 | # -*- coding: utf-8 -*-
<%inherit file="/base.mako" />
<%def name="head_tags()">
<!-- add some head tags here -->
</%def>
<h1>My Controller</h1>
<p>Lorum ipsum dolor yadda yadda</p>
|
Here we define the functions called by base.mako.
- The inherit tag specifies a parent file to pass program flow to
- Mako defines functions with <%def name="function_name()">...</%def>, the contents of the tag are returned
- Anything left after the Mako tags are parsed out is automatically put into the body() function
If all your application pages refer back to single file (in this case base.mako), you can keep a consistent feel to your application.
Rendering a Mako template from a controller
In your controller action, use the following as a return() value,
1 | return render('/my_action.mako')
|
Now run the action, usually by visiting something like http://localhost:5000/my_controller/my_action
in your browser (if Pylons is running)
If you do 'View Source' in your browser the output should be the following,
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<!-- add some head tags here -->
</head>
<body>
<h1>My Controller</h1>
<p>Lorum ipsum dolor yadda yadda</p>
</body>
</html>
|
Passing variables to Mako from the controller
Add the following to your controller action just before the return line,
1 | c.title = 'Mr Jones lives!'
|
and now in myapp/template/my_action.mako add the following in place of <!-- add some head tags here -->,
1 | <title>${c.title}</title>
|
Now when run the browser window title should read 'Mr Jones lives!'
- The c object is passed to Mako from the controller
Using Webhelpers
The Webhelper functions are available in Mako templates under the h object. Some useful ones are,
- h.stylesheet_link_tag('base') - This returns a link tag to a static stylesheet named base.css in myapp/public/stylesheets
- h.javascript_include_tag('base') - This return a script tag to a static javascript file named base.js in myapp/public/scripts
Routes for people in a hurry describes how you should generate internal application URIs using Webhelpers
The rest of the webhelpers are documented pretty consicely in main Webhelper documentation
.
Python in Mako
You can include arbitrary Python code in Mako by enclosing it in <% and %> i.e. Note that to actually output the text from a Python block in your Mako template, you need to write to the template context
.
1
2
3
4
5 | <%
c.mr_jones.age = datetime.date.year() - c.mr_jones.birthday.year
if c.mr_jones.age > 12:
context.write('<p>Sorry Mr Jones, you are too old for Pandas Palace!</p>')
%>
|
We can also use Pythons flow control elements (for, while, if etc.) more directly with slight modification,
1
2
3
4 | %if c.mr_jones.age > 12:
<p>Sorry Mr Jones, you are too old for Pandas Palace!</p>
<p>Try Barry's Bingo instead</p>
%endif
|
- Flow is opened with %<flow_element> and must be 'closed' with %end<flow_element>
Further reading
You may add a sentence about UTF8 encoded templates (see the Cheatsheet
.)
And a small caveat: you can spread a ${ ... } expression across several lines. But the "}" must not be alone on a line or Mako will complain. Always put it on the line with the rest of an expression.