Jinja

From XPUB & Lens-Based wiki

Jinja2

Jinja is one of many templating engine for Python.

Although is usually used to generate HTML pages, it is not restricted.

In other words, you can use Python programming structures likes lists, dictionaries, loops, conditions, etc to generate HTML pages, since often then a HTML page has a lot of fixed,munchanging elements, and some variable elements.

This makes ideal for templating, by using the same template like a blueprint, and giving its variable elements different values at different times, we can save a lot of effort.

Install Jinja2

Unlike the Python modules used previously Jinja2 is not part of Python standard library, therefore we need to first install it before importing it into our scripts.

First, we need to make a virtual environment (venv in short): $ python3 -m venv venv

This makes a folder with the name "venv" in the current folder you are. You can use a different name, it does not matter, but i like to use "venv" just to tell myself what this folder is :).

The command above just created this folder for you, and installed a standalone version of Python there. It's basically a local version of Python, and allows you to install specific libraries. It's a way to not mess up with different versions of libraries over time.

Anyway! Now, we need to activate this venv: $ source venv/bin/activate

And install Jinja2 with pip: pip install jinja2

More on Jinja2

Example scripts

Loading images from a folder

This example is for Kiara, Chrissy and Tessa to make their hyperzine project as part of SI26: Declarations.

To use it:

  1. First activate the venv: $ source venv/bin/activate
  2. Then run the Python script: $ python3 make_html_page.py
  3. Tada, now visit your page in the browser!

make_html_page.py:

import os
from jinja2 import Template

# first we will load all the images

all_images = os.listdir("images") # "images" is the foldername where images are stored
print(all_images)

# then we load our template

template_file = open("template.html", "r").read()
template = Template(template_file)

# then we use the template to render the html

html = template.render(images=all_images)
print(html)

# and then we will save the html to a file

hyperzine = open("index.html", "w")
hyperzine.write(html)
hyperzine.close()

template.html:

<!DOCTYPE html>
<html>
<head>
<style>
        img{
                width: 100px;
                display: inline-block;
        }
</style>
</head>
<body>

This is how you can use a variable from python in your html page. <br>
This is the variable that holds all the images: {{ images }}

<br>
<br>

And this is how you can loop through this list and display each image:

<br>
<br>

{% for image in images %}
<img src="images/{{ image }}">
{% endfor %}

<br>
<br>

<small>
Remember! Each time you make a change in the template file, you will need to run the python script and generate the html page again.
<br>
Tip! If you work with a linked stylesheet, you don't have to generate the page after each change you made in CSS.
</small>

</body>
</html>

A trace from SI "Interfacing the law"

import jinja2

template = jinja2.Template('Hello {{ name }}!') #the simplest template with a variable:name
print 'Simple template rendered:', template.render(name='Pirate'), '\n' # render it giving a value to variable name


# templates can be more complex this for a HTML table row
row_template = jinja2.Template(''' <tr>
<td>{{library}}<td> 
<td>{{author}}<td> 
<td><a href="{{link}}">Go<td>
</tr> ''') # notice: use of ''' allows strings to be multi-line

# to fill it will use a dictionary
piratelibs = {
        'Memory_or_the_World': {'author':'Marcel Mars', 'site':'http://memoryoftheworld.org/'},
        'aaaarg': {'author':'Sea Dockray', 'site':'http://aaaaarg.fail/'},
         'Monoskop':{'author':'Dusan Barok', 'site':'http://monoskop.org/'},
         'Sci-hub': {'author':'Alexandra Elbakyan', 'site':'http://sci-hub.bz/'}
    }

# And render the template w/ the details from one piratelib

onerow = row_template.render( library='aaaarg', author=piratelibs['aaaarg']['author'], link=piratelibs['aaaarg']['site'] )
print 'row_template rendered:', onerow, '\n'


allrows=""
# what if we want to render all the pirate libs?
# then the for loop is our friend 
for lib in piratelibs.keys(): # for each entry get its key value
    #print 'key:', lib 
    #print 'value (dict):', piratelibs[lib] 
    # since the value is also a dictionary we get its values by invoking its keys: author, site
    #print piratelibs[lib]['author']
    #print piratelibs[lib]['site']
    # now we have all the elements necessary to render the template
    onerow = row_template.render( library=lib, author=piratelibs[lib]['author'], link=piratelibs[lib]['site'] )
    print onerow
        
# Challange #1: change the loops so that at each loop iteration onerow adds itself to allrows varible
# in order to get 1 large HTML string containing all row?

# Challange #2: add the content allrows in HTML template containing <!DOCTYPE html>,<html>,<body>, and <table> tag