Main menu

Post navigation

Templating With Jinja2 in Flask: Essentials

Jinja2 is a template engine written in pure Python. It provides a Django-inspired non-XML syntax but supports inline expressions and an optional sandboxed environment. It is small but fast, apart from being an easy-to-use standalone template engine. Flask is a Python-based micro web framework which allows you to write your web applications quickly and efficiently.

In this three-part series, I will start with the basics of Jinja2 templating from the perspective of Flask. In the subsequent parts of this series, I will cover advanced templating topics while learning how to lay out templates in a Flask-based application in a modular and extensible design.

I assume that you have a basic understanding of Flask and environment setup best practices using virtualenv to be followed while developing a Python application.

Installing Packages

Flask comes packaged with Jinja2, and hence we just need to install Flask. For this series, I recommend using the development version of Flask, which includes much more stable command line support among many other features and improvements to Flask in general.

pip install https://github.com/mitsuhiko/flask/tarball/master

Need for a Templating Engine?

In Flask, we can write a complete web application without the need of any third-party templating engine. Let’s have a look at a small Hello World app below:

It is obvious that the above pattern of writing an application is not feasible in case of a real web application where HTML, CSS and JS code ranges in thousands of lines of code. Here, templating saves us because we can structure our view code by keeping our templates separate. Flask provides support for Jinja2 by default, but any other templating engine can also be used as suited.

Laying Out Templates

By default, Flask expects the templates to be placed in a folder named templates at the application root level. Flask then automatically reads the contents by making this folder available for use with the render_template() method. I will demonstrate the same by restructuring the trivial Hello World application shown above.

Try opening the URL with your name as the last part of it. So if your name is John, the URL would be http://127.0.0.1:5000/hello/John. Now the page would look like this:

It is pretty straightforward that in the method hello_world the last part of the URL after hello is fetched from the request and passed to the context of the template being rendered using render_template(). This value is then parsed from the template context using the Jinja2 placeholder {{ user }}. This placeholder evaluates all the expressions that are placed inside it, depending on the template context.

Understanding Blocks and Inheritance in Templates

Usually, any web application will have a number of web pages that will be different from each other. Code blocks such as headers and footers will be the same in almost all the pages throughout the site. Likewise, the menu also remains the same. In fact, usually, just the center container block changes, and the rest usually remains the same. For this, Jinja2 provides a great way of inheritance among templates. It’s a good practice to have a base template where we can structure the basic layout of the site along with the header and footer.

I will create a small application to showcase a list of products under different categories. For styling, I will use the Bootstrap framework to give a basic design to the templates. The application structure is now as shown below.

In this file, I have hardcoded the product list to make the application simpler and focus only on the templating part. I have created two endpoints, home and product, where the former serves the purpose of listing all the products and the latter opens up the individual page.

Note the use of url_for() for creating URLs for static files and other links. It is a very handy tool which is provided by Flask. Read more about this in the documentation. Another important point to note here is the usage of {% block container %}{% endblock %}, which is very crucial component of Jinja2 working towards making the templates modular and inheritable. The next couple of files will make this clearer.

See how this template extends base.html and provides the contents of {% block container %}. {% for %} behaves just like a normal for loop in any language which we are using here to create a list of products.