Log in

Templates

Warning:

Work in progress

This first section is a bit of history and a general introduction to Templating using, ahem php.

php

.php and .asp (MS Active Server pages) are templating engines. They allow scripts to "inject and output" content intermixed with the html, as shown in the following simple snippet.

<?php
// This is hello.php
$js_libs = array('/js/jquery.js', '/js/extjs.js','http://code.google.maps/3/map.js');
$title = 'Hello php';
?>
<html>
<title><?php echo str_to_upper($title); ?></title>
<?php
foreach($js_libs as $xlib){
   echo "<script href='".$xlib.'>';
}
?>
<link ref="stylesheet></link>

As you can see, php script and html and intermixed, its messy and difficult to maintain.

php with Smarty templating

Here is the same output, but this time with Smarty templating and two files; hello.php and hello.html, the logic and presentation respectively.

<?php
// This is hello.php with no html, instead variables are passed/assigned to smarty
require('Smarty.class.php');
$smarty = new Smarty();

$js_libs_to_load = array('/js/jquery.js', '/js/extjs.js','http://code.google.maps/3/map.js');
$smarty->assign('js_libs', $js_libs_to_load);
$Smarty->assign('title','Hello smarty');

$smarty->display('hello.html');
?>
{* this is the smarty template hello.html *}
<html>
<title>{$title|upper}</title>
{foreach from=$js_libs item=xlib}
 <script href='{$xlib}'>
{/foreach}
<link ref="stylesheet></link>

Tipfy with Jinja2

Below is the same script, but this time with Jinja2 templating and the tipfy.ext.jinja2 extension. The main "goal" is to seperate the "logic" form the "presentation", and hence two files. The variables "passed" between the two is a "context" as is a dictionary.

# Import the Request Handler
from tipfy import RequestHandler

# Using Jinja templating 
from tipfy.ext.jinja2 import render_response

# The Handler
class HelloWorldHandler(RequestHandler):

    # Executed with GET request
    def get(self, **kwargs):

        # Our python dictionary of "stuff", in this case a list of js files, and a title
        context = {'js_libs': ['/js/jquery.js', '/js/extjs.js','http://code.google.maps/3/map.js'],
                   'title': 'Hello Jinja'
        }
        return render_response('hello.html', **context)
{# This is hello.html - a Jinja2 template #}
<html>
<title>{{ title|upper }}</title>
{% for xlib in js_libs %}
  <script href='{{ xlib }}'>
{% endfor %}
<link ref="stylesheet"></link>

Note:

  • Templates are located in the templates/ directory and is a path created in the tipfy.ext.jinja2.default_config.
  • The templates/ directory can be structured, nested as required eg
    • render_response('/my_mod/page.html')
    • render_response('my_mod.page.html')
  • The filename extension is up to you. This example used hello.html for its convenience with editors, but some developers prefer hello.jinja or hello.mako for example.

Context

  • The context are keyword arguments to be used in the template; as hello.html above.
  • Jinja2 "presents" these variables in the template eg {{ title }}
# pass variables as params
render_response('hello.html', title='My Title', js_libs=['foo.js', 'bar.js'])

This does the same, but the **context expands the dictionary "keys" into parameters.

# pass a dictionary context as params
mystuff = {'js_libs': ['/js/jquery.js', '/js/extjs.js','http://code.google.maps/3/map.js'],
                   'title': 'Hello Jinja'
        }

## **mystuff is expanded to 'js_libs' and 'title'
render_response('hello.html', **mystuff)

More Context

Let's consider this more complex example. In this case, we're creating three template variables, with multiple data.

## Page data, assumed curr_page is eg 'foo'
page = {}
page['page'] = curr_page
page['title'] = 'Page Title'
page['content'] = my_module.fetch_some_content(curr_page)

## Stuff with libs
libs = {}
libs['js_core'] = ('foo.js','bar.js')
libs['css'] = ('/css/foo.css','http://mega.com/bar.css')

## Current user
curr_user = get_current_user()

## pass the variables to template, page as "p" , libs as 'L', user a 'u'
return render_response('foo.html', p=page, L=libs, u=curr_user)
<html>

<head>
  <title>{{ p.title }}</title>
  
  {% for js in L.js_core %}
  <script src="/js/{{ js }}"/>
  {% endfor %}

  {% for css in L.css %}
  <link rel="stylesheet" href="{{ css }}"/>
  {% endfor %}
</head>

<body>
  <h1>{{ p.title }}</h2>
  <div id="content">{{ p.content }}</div>
  <div id="footer">
    Logged in as <a href="/user/{{u.id}}/">{{ u.name }}</a> - <a href="logout">Logout</a>
  </div>
</body>

</html>

Jinja2 Intergalactic Crash course

TODO - rapid guide to looping, modifiers, variables etc..

Here are some of the tags that can be used in Jinga

{# A comment #}

{# a multi
   lined 
   comment #}

{# This block of code not reguired, ask Brian in sales..
{% for foo in bar %}
<b>{{ foo }}</b>
{% endfor %}
#}

Filters

Jinja variables can by modified by filters. Filters are separated from the variable by a pipe symbol (|) and may have optional arguments in parentheses. Multiple filters can be chained. The output of one filter is the input to the next.

Here are some of the more popular ones:

{# Make first character of each word uppercase #}
<h1>{{ title|capitalize }}</h1>


{# UPPER and lower #}
<b>{{ title|upper }}</b>, <i>{{ title|lower }}</i>


{# Replace an undefined variable #}
<h5>{{ some_variable|default('Oops not there') }}</h5>


{# escape html &, <, > etc to entities #}
<b>{{ title|escape }}</b>, and the shorter <b>{{ title|e }}</b>


{# file size #}
<b> File size: {{ myFile.size.filesizeformat }}</b>


{# length of something #}
<p>Total: {{ membersList|length }}, Total: {{ membersList|count }} is the same</p>


{# select a random item #}
<div id="luck">Lucky number is <b>{{ lucky_numbers|random }}</b></div>


{# replace #}
<h2>{{ title|replace("hello", 'bye') }}</h2>


{# reverse #}
<div>{{ "yfpit"|reverse }}</div>


{# strip tags #}
<p>{{ some_html|striptags }}</p>


{# remove whitespace #}
<p>{{ title|trim }}</p>


{# Filters can be nested, works from right to left  << #}
<div>{{ title|upper|reverse|replace('foo','bar') }}</div>

Template Inheritance

Template inheritance allows you to build a base “skeleton” template that contains all the common elements of your site and defines blocks that child templates can override.

Its Highly recommended you read this section in the Jinja2 documentation (to avoid duplication).

See Also

Templating, Jinja2, Genshi, Mako.

User Comments

None yet.


Powered by Moe. Yeah, the name is Moe. Powered by Google App Engine