Jinja2 templating

In this section, we are going to introduce Jinja2 as a template language that allows you to insert processed data and predetermined text within your HTML code. Basically, Jinja searches and substitutes the names, expressions, and statements that are enclosed by { } within text.

You can see from our preceding views that even when omitting the usual HTML formalities such as <DOCTYPE> and the <html> tag to save complexity, constructing HTML in Python code is clunky. It's difficult to get a feel for the overall page, and it's impossible for designers with no Python knowledge to work on the page design. The templates help to implement the separation between the logic of the backend application and the visual part related to the views.

Flask uses the Jinja2 templating engine for this task. Let's adapt our application to use templates. You can find the following files in the templates folder: base.html, index.html, docstring.html.

The base.html file will look like this:

<!DOCTYPE html>
<html>
<head>
<title>Python Builtins Docstrings</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>

 

The index.html file will be like this:

{% extends "base.html" %}
{% block body %}
<h1>Python Builtins Docstrings</h1>
<div>
{% for func in funcs %}
<div class="menuitem link">
<a href="/functions/{{ func }}">{{ func }}</a>
</div>
{% endfor %}
</table>
{% endblock %}

The docstring.html file will look like this:

{% extends 'base.html' %}
{% block body %}
<h1>{{ func_name }}</h1>
<pre>{{ doc }}</pre>
<p><a href="/">Home</a></p>
{% endblock %}

As you can see, we write a standard page in HTML, with the only difference that there are some bookmarks for the dynamic content enclosed in {{...}} sections.

At this point, you need to use the render_template method that looks in the templates folder for the file that's supplied as the first argument, reads it, runs any processing instructions in the file, then returns the processed HTML as a string. Any keyword arguments that are supplied to render_template() are passed to the template and become available to its processing instructions.

The render_template function takes the filename of the template and a variable list of template arguments to return the template armed with all the arguments replaced. At low level, the Jinja2 template engine is used, which will replace the {{...}} blocks with the values provided as arguments in the render_template function.

You can find the following code in the flaskapp_demo_template.py file on the GitHub repository (https://github.com/PacktPublishing/Learning-Python-Networking-Second-Edition):

#!/usr/local/bin/python

from flask import Flask, abort, render_template

app = Flask(__name__)
app.debug = True
objs = __builtins__.__dict__.items()

docstrings = {name.lower(): obj.__doc__ for name, obj in objs if
name[0].islower() and hasattr(obj, '__name__')}

...

Looking at the templates, we can see they are mostly HTML, but with some extra instructions for Flask contained in {{ }} and {% %} tags. The {{ }} instructions simply substitute the value of the named variable into that point of the HTML. So, for example, the {{ func_name }} in docstrings.html substitutes the value of the func_name value we passed to render_template().

The {% %} instructions contain logic and flow control. For example, the {% for func in funcs %} instruction in index.html loops over values in funcs and repeats the contained HTML for each value.

Finally, you may have spotted that templates allow for inheritance. This is provided by the {% block %} and {% extends %} instructions. In base.html, we declare some shared boilerplate HTML, then in the <body> tag, we just have a {% block body %} instruction. In index.html and docstring.html, we don't include the boilerplate HTML; instead, we extend base.html, meaning that these templates will fill the block instructions that were declared in base.html. In both index.html and docstring.html, we declare a body block, the contents of which Flask inserts into the HTML in base.html, replacing the matching {% block body %} there. Inheritance allows for the reuse of common code, and it can cascade through as many levels as needed.

If we need to apply inheritance within our template, we need to use the extended block in such a way that the template engine allows for the inclusion of a base.html file inside another HTML file. The two templates have a block declaration matching the name of the content, which allows Jinja2 to know how to combine the two into one.

There is a lot more functionality available in Jinja2 template instructions; check out the template designer documentation for a full list, at http://jinja.pocoo.org/docs/dev/templates/.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset