Django template interaction

Robert Crowther Jan 2022

Addresses

In an app,

'appname/page.html'

From the templates/ directory in the project directory,

'page.html'

Extends

A template can contain blocks. These are initially declared empty,

{% block extra_css %}
{% endblock %}

You could add a comment,

{% block extra_css %}
    {# Override this in templates to add extra css links #}
{% endblock %}

How do I fill these blocks? Extend, similar to overriding methods from a base class,

base.html
 └─ page.html

This,

{% extends 'base.html' %}

    {% block extra_css %}
        <link rel="stylesheet" type="text/css" href={% static 'css/page.css' %}>
    {% endblock %}

What happens if I put lines outside the blocks?

{% extends 'base.html' %}

    {% block extra_css %}
        <link rel="stylesheet" type="text/css" href={% static 'css/page.css' %}>
    {% endblock %}

    <div class="duff"></div>

They are lost.

Can I stack templates?

base.html
 └─ page.html
   └─ sitepage.html?

Yes.

Can I choose to fill blocks later? In ’sitepage.html’,

{% extends 'page.html' %}

    {% block extra_css %}
        <link rel="stylesheet" href={% static "css/sitepage.css" %}>
    {% endblock %}

Yes.

What if I fill the same block at different points in the stack? Let’s say the block ‘extra_css’ has entries in ‘page.html’ and ‘sitepage.html’. Output,

<head>
    ...
    <link rel="stylesheet" type="text/css" href="/static/css/sitepage.css">
</head>

Latest entry wins, others are lost (similar to multiple overrides in class inheritance).

What happens if I introduce a new block in a subclass? Let’s say ‘page.html’ has a new block,

{% extends 'page.html' %}

    {% block sitepage_css %}
    {% endblock %}

No. The analogy to class inheritance has broken down. Think about it and you will see that ordering is important to templates, unlike with classes. Django wouldn’t know where to place this new block. You would need to revise ‘base.html’,

<head>
    ...
    {% block extra_css %}
    {% endblock %}
    {% block sitepage_css %}
    {% endblock %}
</head>

Makes sense (how would you do that?). But also a limitation, because you need more blocks in the base, to account for possible overriding. And they cant be specific to the subclass.

Can I nest blocks? Can I introduce new blocks like that (on face, this seems to answer the question ‘Where does the template system place this new material?’)?

{% extends 'page.html' %}

    {% block extra_css %}
        <link rel="stylesheet" type="text/css" href={% static 'css/page.css' %}>
        {% block sitepage_css %}
        {% endblock %}
    {% endblock %}

Yes. It feels tricky, but it works.

Includes

A snippet of template to use in another template.

{% includes "form.html" %}

Can you do this inside extend templates like the stack above? Yes. The ‘include’ must be inside a block.