Creating Web Pages with the Jinja Templating System

In the last section of this chapter we are going to create another script, this one generating a simple structure of web pages containing the graphs. The main entry page lists all available checks grouped by the system and links to the check details page. When a user navigates to that page, she will see the graph generated by RRDTool and some details about the check itself (such as the check description and OID). Now, this looks relatively easy to implement, and most people would simply start writing a Python script that would use print statements to produce the HTML pages. Although this approach may seem to work, in most cases it soon becomes unmanageable. The functional code often becomes intermingled with the content-producing code, and adding new functionality usually breaks everything, which in turn leads to hours spent debugging the application.

The solution to this problem is to use one of the templating frameworks, which allow decoupling the application logic from the presentation. The basic principle of a templating system is simple: you write code that performs calculations and other tasks that are not content-specific, such as retrieving data from the databases or other sources. Then you pass this information to the templating framework, along with the name of the template that uses this information. In the template code you put all HTML formatting text together with the dynamic data (which was generated earlier). The framework then parses the template for simple processing statements (like iteration loops and logical test statements) and generates the result. You can see the basic flow of this processing in Figure 1-6.

Django Template System
Figure 1-6. Data flow in the templating framework

This way, your application code is clean from all content-generation statements and is much easier to maintain. The template can access all variables presented to it, but it looks more like an HTML page, and loading it in a web browser usually produces acceptable results. So you can even ask a dedicated web developer to create the templates for you, as there is no need to know any Python to modify them.

I'm going to use a templating framework called Jinja, which has syntax very similar to that used by the Django web framework. We're also going to talk about the Django framework in this book, so it makes sense to use a similar templating language. The Jinja framework is also widely used, and most Linux distributions include the Jinja package. On a Fedora system you can install it with the following command:

$ sudo yum install python-jinja2

Alternatively, you can use the PiP application to install it: $ sudo pip install Jinja2

You can also get the latest development version of the Jinja2 framework from the official web site: http://jinja.pocoo.org/2/.

■Tip Make sure to install Jinja2 and not the earlier release—Jinja. Jinja2 provides an extended templating language and is actively developed for and supported.

Loading Template Files with Jinja2

Jinja2 is designed to be used in the web framework and therefore has a very extensive API. Most of its functionality is not used in simple applications that only generate a few pages, so I'm going to skip those functions, as they could be a topic for a book of their own. In this section I'll show you how to load a template, pass some variables to it, and save the result. These three functions are what you will use most of the time in your applications. For more extensive documentation on the Jinja2 API, please refer to http://jinja.pocoo.org/2/documentation/api.

The Jinja2 framework uses so called loader classes to load the template files. These can be loaded from various sources, but most likely they are stored on a file system. The loader class, which is responsible for loading the templates stored on a file system, is called jinja2. FileSystemLoader. It accepts one string or a list of strings that are the pathnames on a file system where the template files can be found:

from jinja2 import FileSystemLoader loader1 = FileSystemLoader('/path/to/your/templates') loader2 = FileSystemLoader(['/templates1/', '/teamplates2/']

Once you initialized the loader class, you create an instance of the jinja2. Environment class. This class is the central part of the framework and is used to store the configuration variables, access the templates (via the loader instance), and pass the variables to the template objects. When initializing the environment, you must pass the loader object if you want to access externally stored templates:

from jinja2 import Environment, FileSystemLoader loader = FileSystemLoader('/path/to/your/templates') env = Environment(loader=loader)

When the environment has been created, you can then load the templates and render the output. First you call the get_template method, which returns a template object associated with the template file. Next you call the template object's method render, which processes the template contents (loaded by the previously initialized loader class). The result is the processed template code, which can be written to a file. You have to pass all variables to the template as a dictionary. The dictionary keys are the names of the variables available from within the template. The dictionary values can be any Python objects that you want to pass to the template.

from jinja2 import Environment, FileSystemLoader loader = FileSystemLoader('/path/to/your/templates')

env = Environment(loader=loader)

template = env.get_template('template.tpl')

result = template.render({'name': name, 'age': age})

r_file.write(result)

r_file.close()

The Jinja2 Template Language

The Jinja2 templating language is quite extensive and feature-rich. The basic concepts, however, are quite simple and the language closely resembles Python. For a full language description, please check the official Jinja2 template language definition at http://jinja.pocoo.org/2/documentation/templates.

The template statements have to be escaped; anything that is not escaped is not processed and will be returned verbatim after the rendering process. There are two types of language delimiters:

• The variable access delimiter, which indicates a reference to a variable: {{ ... }}

• The statement execution delimiter, which tells the framework that the statement inside the delimiter is a functional instruction: {% ... %}

Was this article helpful?

+4 0

Responses

  • ren
    How to make web pages with jinja2?
    8 years ago

Post a comment