Jinja templates: Storage and Inheritance using Database

How to store Jinja templates in database and use template inheritance using database

Jinja is a web template engine for the Python programming language. A Jinja template is simply a text file and can generate any text-based format (HTML, XML, CSV, LaTeX, etc.). A template contains variables and/or expressions, which get replaced with values when the template is rendered, thus serving dynamic content.

Commonly, templates are stored as files, either in git-repo or s3 buckets. Depending on your use case, you can store the templates in the database as well.

Templates in Database

  • Template is a text file and hence can be simply saved in the text field of the database.

  • This text file can be retrieved from the database and Jinja can be used to render the template, like done below

1
2
3
4
5
# example of template
template = "template with name: {{name}}"

from jinja2 import Template
print(Template(template).render({"name": "wilspi"})

This will give the rendered template output.

Template Inheritance and Database

Template inheritance is where Jinja’s power lies. It allows you to reuse templates and structure them in an efficient manner.

Jinja allows template inheritance via many techniques, few of which are listed below:

But all these ways require templates to be present in the same Jinja environment That’s how Jinja picks up the other templates while using all these inheritance techniques.

The most common way to use inheritance is to use file system loader which puts the base directory path in the environment and then jinja can pick/load any of these files to render since all of them are in its environment.

With templates being in the database, we need a way to load templates into Jinja environment, since Jinja doesn’t support any environment using the database.

DictLoader is another loader which loads key-value pairs in the Jinja environment. A dictionary of templates can be created by loading templates from the database, and then we can use DictLoader to load these templates into Jinja environment, and Voila!, Jinja’s inheritance system works like a charm.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
template_map = {
    "header": "header template",
    "base": """
    {% include "header" %}
    base template with {{name}}
    {% include "footer" %}
    """,
    "footer": "footer template",
}

from jinja2 import Environment, DictLoader
env = Environment(loader=DictLoader(template_map))

print(env.get_template("base").render({"name":"wilspi"})))