Latest Version: 0.9.6.2
  Dashboard > Pylons Cookbook > ... > Guides to Pylons for people in a hurry > Mako for people in a hurry
  Pylons Cookbook Log In | Sign Up   View a printable version of the current page.  
  Mako for people in a hurry
Added by Brendan Arnold, last edited by Brendan Arnold on Jun 08, 2008  (view change)
Labels: 

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,

easy_install -U Mako

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,

1
# -*- coding: utf-8 -*-

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.

Posted by Christoph Haas at May 31, 2007 10:47 | Permalink

Cheers for the tips. I added the bit about ${...} however I don't have any experience in using Unicode in Pylons and since I'm on away from my computer for the next ten days or so I can't try out examples. I can add a section in a couple of weeks or, if you like, you are welcome to add something yourself in the spirit of the guides i.e. fits in a short section and it works!

Posted by Brendan Arnold at Jun 01, 2007 21:21 | Permalink
Site running on a free Atlassian Confluence Open Source Project License granted to Pylons. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.3.3 Build:#645 Feb 13, 2007) - Bug/feature request - Contact Administrators
Top