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> but click <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