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 thetipfy.ext.jinja2.default_config. - The
templates/directory can be structured, nested as required egrender_response('/my_mod/page.html')render_response('my_mod.page.html')
- The filename extension is up to you. This example used
hello.htmlfor its convenience with editors, but some developers preferhello.jinjaorhello.makofor example.
Context¶
- The context are keyword arguments to be used in the template; as
hello.htmlabove. - 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>
- Jinja Builtin Filters documentation.
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.
- Version: latest
- Edited by cpeterso on 11/30/10 5:57 PM
- Save on Delicious | Submit to Reddit
- History
- Edit
