Web Technologies/2021-2022/Laboratory 4

Templating engines

edit

A Templating Engine is software that is designed to process templates and content information to produce output documents. It can be successfully used in Web content generation. It allows separating

Examples include:

  • Jinja (Python)
  • Velocity (Java)
  • Freemarker (Java)
  • JavaServerPages (Java)
  • Phptal (PHP)
  • Smarty (PHP)
  • ActiveServerPages (.NET)
  • XSLT (XML)

The main advantages of Templating Engines is that they:

  • Enforce the separation of functional responsibility (eg. designer from programmer)
  • Promote division of labor
  • Provide easier syntax
  • Increase security

Templating Engines can be used in:

  • Servlet-based Web applications
  • Java and SQL code generation
  • XML processing and transformation
  • Text processing, such as RTF file generation

Examples

edit

Jinja2 with the Flask framework

edit

Jinja is the most widely used templating engine for Python. It is inspired from Django's templating language and it's also Flask's default engine. The project's homepage is https://jinja.palletsprojects.com/en/2.11.x/

Since jinja2 is already in the PyPi repositories, one can easily install it with Python's package manager, pip. The command installing Jinja2 directly is (NOTE: you can directly use pip install Flask, as the Flask package has a dependency for Jinja2 and it will automatically get installed):

pip install Flask

Using a virtual environment (optional)

edit

Since installing Python packages directly on your operating system is not recommended, using Python's virtual environments is usually a good idea. The principle here is to have a separate Python distribution and to install packages inside the separated environment. Creation and activation of a virtual environment works as such:

virtualenv -p PythonX.X <venv-name>
source <venv-name>/bin/activate

Or (in the case you are using Microsoft Windows):

C:\Python35\python -m venv X:\path\to\myenv
C:\> <venv>\Scripts\activate.bat

Where X.X is the desired Python version the environment should contain, and <venv-name> is it's desired name. Once created and activated, one can check using the which python or which pip command to validate the fact the virtual environment's Python distribution is being used.

Flask app definition

edit

We will use the minimal Flask framework, as by default Flask utilizes the Jinja templating engine.

import xml.etree.ElementTree as ET

from flask import Flask, render_template
import jinja2

app = Flask(__name__)

@app.route('/')
def display_content(content=None):
    xml_tree = ET.parse('queue.xml').getroot()
    return render_template('template.html', content=xml_tree)

Here's what the template.html file looks like:

<title>Reading Queue</title>

<ul>
  {% for entry in content %}
  <li>
    <strong>{{ entry[0].text }}</strong>
    <a href="{{ entry[1].text }}">{{ entry[1].text }}</a>
  </li>
  {% endfor %}
</ul>

In order to run the example one must have the following directory structure:

.
├── index.py
├── queue.xml
└── templates
│   └── template.html
└── venv

In order to run the web application with flask, the environment variable FLASK_APP has to point to index.py:

export FLASK_APP=index.py

Or if running Microsoft Windows:

SET FLASK_APP=index.py

Then, starting the app:

flask run

Jinja2 also includes a set of directives:

  • %if
  • %else
  • %elif
  • %for
  • %raw
  • %extends

Velocity

edit

Download from : Apache Velocity - Download Page (Project website http://velocity.apache.org/download.cgi)


When using Velocity, information is usually retrieved from beans. Consider for example the following code which displays Welcome John to your first Velocity application. Your email address is john@student.com.

import java.io.StringWriter;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
 
public class VelocityTest {
	public static void main( String[] args ) throws Exception {
		// Get and initialize an engine
		VelocityEngine ve = new VelocityEngine();
		ve.init();
		// Get the Template
		Template t = ve.getTemplate( "hello.vm" );
		// Create a context and add data
		VelocityContext context = new VelocityContext();
		UserInfo user = new UserInfo("John", "john@student.com");
		context.put("user", user);
		// Render the template into a StringWriter
		StringWriter writer = new StringWriter();
		t.merge( context, writer );
		// Show the result
		System.out.println( writer.toString() ); 
	}
}
 
public class UserInfo {
	private String user, email;
 
	public UserInfo (String name, String email) {
		this.user = name;
		this.email = email;
	}
 
	public String getUser() {
		return this.user;
	}
 
 
	public String getEmail() {
		return this.email;
	}
}

where the hello.vm file looks like:

Welcome $user.user to your first Velocity application. Your email address is $user.email.

IMPORTANT: notice that we do not have to use the exact getters for retrieving the value of the fields. Velocity takes care of that for use by using Java Reflection.

You can also use directives such as:

  • #set()
  • #if()
  • #else
  • #elseif()
  • #end
  • #foreach()
  • #include()
  • #parse()
  • #macro()

A complete reference for template syntax can be found here.


Links:

Exercises

edit
  • Start from the data in XML format from the previous laboratory. Create beans and/or lists for it and populate them with data directly from within Java / Python code.

Generate the same HTML code, as in the previous laboratory, using a Velocity or Jinja template.

Gabriel Iuhasz, 2014-10-01, iuhasz.gabriel@e-uvt.ro

Alexandru Munteanu 2021-10-16, mailto:alexandru.munteanu@e-uvt.ro