Templates and Views in Flask with Jinja2

Templates and Views in Flask with Jinja2

PART 3: A deep dive into Jinja2

Flask is a popular web framework for Python that allows you to create dynamic web applications with minimal code. One of the features that make Flask powerful and flexible is its support for templates and views.

What are templates?

Templates are files that contain static data as well as placeholders for dynamic data. A template is rendered with specific data to produce a final document, such as an HTML page. Flask uses Jinja2 as its default template engine, which provides a rich set of features for creating expressive and reusable templates. Views are functions that handle requests to your application.

They are responsible for performing the logic of your application, such as fetching data from a database or an API, processing user input, or performing calculations. Views also return responses to the client, which can be either plain text, JSON data, or rendered templates. In this post, we will cover how to create dynamic templates and views in Flask, including how to use Jinja2 templates to display data in your web application.

Creating Templates

To create a template in Flask, you need to store it in a folder called templates inside your application package or module. For example, if your application is called app.py, you can create a folder called app/templates and store your templates there. A template file can have any extension, but it is recommended to use .html for HTML templates. A template file can contain any valid HTML code as well as Jinja2 syntax for placeholders and expressions. Here is an example of a simple template file called index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Flask Template Example</title>
</head>
<body>
    <h1>Hello {{ name }}!</h1>
    <p>This is an example of a Flask template.</p>
</body>
</html>

In this template file, we have a placeholder {{ name }} that will be replaced with a value when the template is rendered. We also have some static HTML code that defines the structure and style of the page.

Rendering Templates

To render a template in Flask, you need to use the render_template() function from the flask package. This function takes the name of the template file as its first argument and any additional arguments as keyword arguments that will be passed to the template context.

A template context is a dictionary-like object that contains all the variables and functions that are available to the template when it is rendered. The keyword arguments passed to render_template() are added to the template context automatically.

Here is an example of how to render our index.html template from a view function:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html', name='Flask')

In this code block, we import the Flask class and the render_template() function from the flask package. We use the Flask class to create our Flask application instance named app. Then we define a view function (which is a Python function that returns an HTTP response) called index() using the app.route() decorator, which converts it into a route handler for requests matching /.

Inside our view function, we call render_template() with two arguments: 'index.html', which is the name of our template file; and 'Flask', which is assigned to the keyword argument name. This means that when our template is rendered, the placeholder {{ name }} will be replaced with ‘Flask’.

The app.py file could be run using this command $ flaskapp.py.

As you can see, our view function has returned an HTML page generated by rendering our index.html template with ‘Flask’ as its nominal value.

Using Template Inheritance

One of the advantages of using templates in Flask is that you can reuse common elements across different pages using inheritance. Template inheritance allows you to define a base layout for your web application and then extend it with specific content for each page.

To use inheritance in Jinja2 templates, you need two keywords: {% extends %} and {% block %}.

The {% extends %} keyword tells Jinja2 which base layout or parent template you want to inherit from. It should be placed at the top of your child or sub-template file.

The {% block %} keyword defines a block of content that can be overridden by the child template. It should be placed inside the parent template where you want to insert the child content. You can have multiple blocks with different names in your parent template.

Here is an example of a base layout or parent template file called layout.html:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/about">About</a></li>
            <li><a href="/contact">Contact</a></li>
        </ul>
    </nav>

    {% block content %}
    {% endblock %}
</body>
</html>

In this template file, we have two blocks: title and content. The title block will be used to insert the page title in the <head> section, and the content block will be used to insert the main content of the page in the <body> section.

We also have some static HTML code that defines a navigation bar with three links: Home, About, and Contact. This navigation bar will be common for all pages that inherit from this layout.

To inherit from this layout, we need to create a child or sub-template file that extends it using {% extends %} and overrides its blocks using {% block %}. Here is an example of a child template file called home.html:

{% extends "layout.html" %}

{% block title %}
Home
{% endblock %}

{% block content %}
<h1>Welcome to Flask Template Example</h1>
<p>This is the home page.</p>
{% endblock %}

In this template file, we extend our layout.html file using {% extends "layout.html" %} at the top. Then we override its two blocks: title and content. We set the title to ‘Home’ and we add some HTML code for our home page content.

To render this child template from a view function, we just need to call render_template() with its name as an argument:

@app.route('/')
def home():
    return render_template('home.html')

As you can see, our view function has returned an HTML page generated by rendering our home.html template with our layout.html as its base layout.

We can create more child templates for other pages using the same technique. For example, here is a child template file called about.html:

{% extends "layout.html" %}

{% block title %}
About
{% endblock %}

{% block content %}
<h1>About Flask Template Example</h1>
<p>This is a simple web application that demonstrates how to use templates and views in Flask.</p>
{% endblock %}

And here is how we render it from a view function:

@app.route('/about')
def about():
    return render_template('about.html')

As you can see, our view function has returned an HTML page generated by rendering our about.html template with our layout.html as its base layout.

Conclusion

In this post, we have learned how to create dynamic templates and views in Flask using Jinja2 templates. We have seen how to use placeholders and expressions to insert data into templates, how to use inheritance to reuse common elements across different pages, and how to render templates from view functions using render_template().

Templates and views are essential components of any web application that allow you to separate your presentation logic from your business logic. By using templates and views in Flask, you can create web applications that are modular, maintainable, and scalable.