Create reusable Jinja templates

Templates tend to have common sections that are equally used across multiple instances. For example, the header and footer sections on all templates rarely changes, whether a project has five or one hundred templates. Other template sections like menus and advertisements, also fall into this category of content that's constant across multiple templates. All of this can lead to repetition over multiple templates, which can be avoided by creating reusable templates.

With reusable Jinja templates you can define common sections on separate templates and reuse them inside other templates. This process makes it easy to create and manage a project's templates because a single template update takes effect on all templates.

Reusable Jinja templates also allow you to define page blocks to override content on a page by page basis. This process makes a project's templates more modular because you define top level blocks to establish the overall layout and define content on a page by page basis.

Lets take the first step toward building reusable Jinja templates by exploring Jinja's built-in {% block %} tag. Listing 4-5 illustrates the first lines of a template called base.html with several {% block %} tags.

Listing 4-5. Jinja template with {% block %} tags

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>{% block title%}Default title{% endblock title %}</title>
    <meta name="description" content="{% block metadescription%}{% endblock metadescription %}">
    <meta name="keywords" content="{% block metakeywords%}{% endblock metakeywords %}">

Notice the syntax {% block <name>%}{% endblock <name>%} in listing 4-5. Each {% block %} tag has a reference name. The reference name is used by other Jinja templates to override the content for each block. For example, the {% block title %} tag within the HTML <title> tags defines a web page title. If another template reuses the template in listing 4-5, it can define its own web page title by overriding the title block. If a block is not overridden on a template, the block receives the default content within the block. For the title block the default content is Default title, for the metadescription and metakeywords blocks the default content is an empty string.

The same mechanism illustrated in listing 4-5 can be used to define any number of blocks (e.g. content, menu, header, footer). It's worth mentioning the <name> argument of {% endblock <name> %} is optional and it's valid to just use {% endblock %} to close a block statement, however, the former technique makes it clearer where a block statement ends which is specially helpful when a template has multiple blocks.

Although it's possible to call the template in listing 4-5 directly by a Django view method or url request, the purpose of this kind of template is to use it as a base template for other templates. To reuse a Jinja template you use the Jinja built-in {% extends %} tag.

The {% extends %} tag uses the syntax {% extends <name> %} to reuse the layout of another template. This means that in order to reuse the layout in listing 4-5 defined in a file base.html, you use the syntax {% extends "base.html" %}, as illustrated in listing 4-6.

Listing 4-6. Jinja template with {% extends %} and {% block %} tag

{% if user %}{% extends "base.html" %}{% else %}{% extends "signup_base.html" %}{% endif %}
{% block title %}Coffeehouse home page{% endblock %} 

Look how listing 4-6 uses the {% extends "base.html" %} wrapped around the {% if user %} statement. If the user variable is defined, Jinja extends the base.html template, otherwise it extends the signup_base.html template. This conditional syntax is not possible in Django templates.