Template reuse: inheritance and template functions

Inheritance

The layout template should be marked up with <py:block> tags to indicate customization points:

<!DOCTYPE html>
<html>
<head>
    <title py:block="title">Default title</title>
</head>
<body>
    <py:block name="content">
    Content goes here
    </py:block>
</body>
</html>

Child templates then use <py:extends href="..."> to pull in the parent’s layout.

Template functions

You can also define reusable template functions:

<!--! File: widgets.html
-->
<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() if callable(content) else content}
                </div>
                <div class="modal-footer">
                    <button type="button">Close</button>
                    <button type="button">Save changes</button>
                </div>
            </div>
        </div>
    </div>
</py:def>

Template functions can be imported into other templates:

<py:import href="widgets.html" alias="widgets"/>
<p>
    ${widgets.modal(content="Hello world!")}
</p>

Notice the ${content() if callable content else content} interpolation in the function body? That’s to support calling the function with py:call, which can pass chunks of template code as keyword arguments. In this case the passed argument will be a callable, which outputs template content.

<py:call function="widgets.modal(fullpage=True)">
    <py:keyword name="content">
        This is the modal content.
        You can include <a href="#">markup</a>
        <py:if test="True">and template directives</py:if> too!
    </py:keyword>
</py:call>