Template Inheritance
The need for modularizing template code arises often in the work of template authors. It is common for websites with multiple pages to share a good amount of code through a base template.
One of the ways to do that with templatel is through template
inheritance. Let's imagine a website with three types of
pages: 1. index, 2. article and 3. about page. We can have one
template for each type of page and have an extra one, called
base.html
to keep the common code shared between the templates for
each page type.
We'll be using two statements to take advantage of template
inheritance: block
and extends
. We must have at least one
template that is considered the "root" of the inheritance tree. In
other words, at least one template must not inherit from any other
templates. Other templates can use the statement extends
to have
access to blocks declared in base templates.
base.html
The base template is where the structure of the HTML document can go and where optional pieces can be made available. A whoever decides to extend this template gets to choose which blocks are filled up and with which content.
<!doctype html> <html lang="en-us"> <head> {% block head %} <meta charset="utf-8"> <title>{% block title %}Cool Website{% endblock %}</title> <meta name="description" content="{% block description %}{% endblock %}"> <meta name="viewport" content="width=device-width, initial-scale=1"> {% endblock %} </head> <body> {% block nav %} <div class="nav"> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> </div> {% endblock %} <div class="document"> {% block page %}{% endblock %} </div> {% block footer %} <div class="footer"> <ul> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> </ul> </div> {% endblock %} </body> </html>
index.html
The template that renders the index page inheriting from the base
template might not necessarily need to display the footer. In that
case, overriding the block
named footer with an empty content is
the solution for that.
{% extends "base.html" %} {% block page %} <div class="page index"> <h1>Cool Website</h1> thoroughly written content... </div> {% endblock %} {% block footer %}{% endblock %}
article.html
The article page does need both the navigation and the footer, so we're not overriding those blocks here.
One thing that could be nice tough is to display the article title
alongside with the website name in the title. When overriding the
title block, we have the option to use super()
to use the
content of the title block of the base.html
template in our
override:
{% extends "base.html" %} {% block title %}{{ super() }} - {{ article.title }}{% endblock %} {% block page %} <div class="page article"> <article> <h1>{{ article.title }}</h1> {{ article.html | safe }} </article> </div> {% endblock %}
about.html
The about page is very similar to the index page. It also doesn't
need a footer. We can extend from this template to take advantage
of that or any other modifications the index.html
template did to
base.html
. Notice that we can still override blocks declared in
the base template:
{% extends "index.html" %} {% block title %}{{ super() }} - About{% endblock %} {% block page %} <div class="page about"> <article> <h1>About</h1> Here goes some content about something </article> </div> {% endblock %}