Directives reference¶
Interpolations¶
Interpolations are delimited by ${...}
(or just a leading $
in the case
of a simple python identifier), and may contain any python expression:
<p class="$cssclass">$body.content</p>
<p>${', '.join(names)}</p>
HTML escaping can be turned off with $!, for example:
$!body.content
$!{', '.join(names)}
You can also mark values as Markup to avoid autoescaping:
${Markup(body.content)}
py:block¶
py:block
defines a block of HTML code that may be customized within a template or a template function. It requires a single name
argument.
Syntax:
<h1 py:block="heading">Heading goes here</h1>
<py:block name="content">Content goes here</py:block>
When used as an attribute, the inner HTML of the element becomes the block. These two forms are equivalent:
<h1 py:block="heading">Heading goes here</h1>
<h1><py:block name="heading">Heading goes here</py:block></h1>
Internally this is compiled to:
def __root__(heading=Markup("Heading goes here")):
yield "<h1>"
yield Markup(heading)
yield "</h1>"
py:call¶
Why use a <py:call>
directive instead of just calling a function as an
interpolation? Because it lets you pass chunks of template code as arguments!
Whatever is inside the <py:call> element is gathered together and compiled to a template function, which is then passed to the function as an argument.
<py:def function="widget(content, size)">
<div class="MyWidget" style="width: ${size}px">${content()}</div>
</py:def>
<py:call function="widget(size=100)">
<!-- This code will be passed as the 'content' argument to 'widget'
-->
<ul>
<li>Fish and chips</li>
<li>Jelly and ice cream</li>
<li>Jelly and chips</li>
</ul>
</py:call>
You can also use the py:keyword
directive to pass multiple arguments:
<py:def function="widget(title, content, size)">
<div class="MyWidget" style="width: ${size}px">${content()}</div>
</py:def>
<py:call function="widget(size=100)">
<h1 py:keyword="title">Today's menu</h1>
<ul py:keyword="content">
<li>Fish and chips</li>
<li>Jelly and ice cream</li>
<li>Jelly and chips</li>
</ul>
</py:call>
Because each template block passed as an argument is compiled to a template function, the function must call the argument to display the HTML. If you want to be able to pass either a string or a template block, use this idiom:
<py:def function="widget(content)">
${content() if callable(content) else content}
</py:def>
py:comment¶
py:comment
causes all content within the directive to be ignored and no
output will be produced.
In the following example, no output will be produced for either element:
<py:comment><h1>The sun was shining on the sea</h1></py:comment>
<p py:comment="Removed due to bad weather">The sun was shining on the sea</p>
py:def¶
Define a template function:
<py:def function="modal(content, title='hello')">
<div class="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" data-dismiss="modal">X</button>
<h4 class="modal-title">$title</h4>
</div>
<div class="modal-body">
$content
</div>
<div class="modal-footer">
<button type="button">Close</button>
<button type="button">Save changes</button>
</div>
</div>
</div>
</div>
</py:def>
The resulting function may be called within a regular python interpolation:
<div>
${modal("I'm sorry Dave, I'm afraid I can't do that", title="Error")}
</div>
Or with a py:call
directive:
<py:call function="modal('fish and chips')"></py:call>
py:extends¶
py:extends
replaces the contained element with the contents of the linked
template file. py:block
arguments can be used to customize code within.
The attribute ignore-missing=""
can be set
to avoid raising an error if the extended template is not found.
In this case, the <py:extends>
element will not be rendered
(including any children)
Example:
<!-- layout.html -->
<html>
<head>
<title py:block="title">Default title</title>
</head>
<body>
<div class="content" py:block="content">Default content</div>
</body>
</html>
<!-- template.html -->
<html py:extends="layout.html">
<py:block name="title">Good morning</py:block>
<py:block name="content">Everybody!</py:block>
</html>
py:include¶
py:include
may be used to include another template file.
The attribute ignore-missing=""
can be set
to avoid raising an error if the included template is not found.
Example:
<html>
<body>
<py:include href="${page}.html" ignore-missing="" />
</body>
</html>
py:filter¶
py:filter
passes the generated string content of the contained template
code through a function:
<p py:filter="lambda s: s.upper()">
This will be rendered in upper case
</p>
py:if¶
py:if
defines a block of HTML code to be displayed conditionally. It
requires a single test
argument.
Syntax:
<h1 py:block="heading">Heading goes here</h1>
<py:block name="content">Content goes here</py:block>
When used as an attribute, the outer HTML of the element becomes the body of the if statement. These two forms are equivalent:
<h1 py:if="oysters">The sun was shining on the sea</h1>
<py:if test="oysters"><h1>The sun was shining on the sea</h1></py:if>
py:choose … py:when … py:otherwise¶
py:choose
defines a block similar to switch statement. The outer
py:choose
block may contain one or more py:when
directives;
only the first one whose test
condition matches will be output.
If no py:when
block matches the contents of any py:otherwise
will be output.
Syntax:
<py:choose>
<py:when test="a == 1">Message 1</py:when>
<py:when test="a == 2">Message 2</py:when>
<py:otherwise>Fallthrough message</py:otherwise>
</py:choose>
<div py:choose="">
<h1 py:when="a == 1">Message 1</h1>
<h1 py:when="a == 2">Message 2</h1>
<h1 py:otherwise="">Fallthrough message</h1>
</div>
py:choose
may also take a test
attribute:
<py:choose test="a">
<py:when="1">Message 1</py:when>
<py:when="2">Message 2</py:when>
<py:otherwise="">Fallthrough message</py:otherwise>
</py:choose>
<div py:choose="a">
<h1 py:when="1">Message 1</h1>
<h1 py:when="2">Message 2</h1>
<h1 py:otherwise="">Fallthrough message</h1>
</div>
py:strip¶
py:strip
causes the containing tag to be omitted from output. With
no arguments, the containing tag is unconditionally stripped. If an expression
argument is given the tag is only stripped if the expression evaluates to True:
<section py:strip="">…</section>
<section py:strip="not ajax_request">…</section>
py:tag¶
py:tag
allows you to dynamically change the tag name of an element:
<img py:tag="'amp-img' if is_amp_request else 'img'" src="…" alt="…"/>
py:whitespace¶
Turns whitespace stripping on or off.
A value of strip
will cause all whitespace elements around opening and
closing tags to be stripped. For example, this:
<div py:whitespace="strip">
<ul>
<li>Hello
World! </li>
</ul>
</div>
would render as this:
<div><ul><li>Hello
World!</li></ul></div>
Within a py:whitespace="strip"
block, py:whitespace="preserve"
can
be used to turn off stripping:
<div py:whitespace="strip">
<ul py:whitespace="preserve">
<li>Hello
World! </li>
</ul>
</div>
Would render as:
<div><ul>
<li>Hello
World!</li>
</ul></div>
Whitespace is stripped according to these rules:
Whitespace is defined as the following characters: space (ascii 0x20), tab (0x09), line feed (0x0a) or carriage return (0x0d). Nonbreaking spaces or other unicode space characters are never stripped.
Whitespace at the start or end of an element is always stripped:
<a> foo </a>
→<a>foo</a>
Whitespace immediately before or after an element is stripped if it contains one or more newline or carriage return characters: So
<li>item 1</li>\n<li>item 2</li>
→<li>item 1</li><li>item 2</li>
butclick <a>here</a>
→click <a>here</a>
.
py:with¶
py:with
allows you to assign variables.
Variables are only in scope within the containing element.
Use semicolons to separate multiple variable assignments.
Examples:
<div py:with="result = calculate_result()">$result</div>
<py:with vars="
author = blogpost.get_author();
pub_date = post.get_publication_date();
">
Published by $author on $pub_date
</py:with>
Whitespace handling¶
Whitespace is maintained as per the input template file, with the following exceptions:
Whitespace between consecutive <py:* > elements is always stripped, eg:
<py:for item="x in range(2)"> <py:for item="y in range(2)">$x, $y </py:for> </py:for>
Would be output on a single line, ie
0, 0, 0, 1, 1, 0, 1, 1
:The py-whitespace directive causes all whitespace to be stripped from around tags inside the element. This includes spaces, tabs, carriage returns and newlines. Non-breaking spaces and other unicode spacing characters are not stripped