How to load jinja template directly from filesystem

PythonTemplatesJinja2

Python Problem Overview


The jinja API document at pocoo.org states:

The simplest way to configure Jinja2 to load templates for your application looks roughly like this:

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))

This will create a template environment with the default settings and a loader that looks up the templates in the templates folder inside the yourapplication python package.

As it turns out, this isn't so simple because you have to make/install a python package with your templates in it, which introduces a lot of needless complexity, especially if you have no intention of distributing your code. You can refer to SO questions on the topic here and here, but the answers are vague and unsatisfying.

What a naive newbie wants to do, obviously, is just load the template directly from the filesystem, not as a resource in a package. How is this done?

Python Solutions


Solution 1 - Python

Here's how: use a FileSystemLoader instead of a PackageLoader. I found examples on the web here and here. Let's say you have a python file in the same dir as your template:

./index.py
./template.html

This index.py will find the template and render it:

#!/usr/bin/python
import jinja2

templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "template.html"
template = templateEnv.get_template(TEMPLATE_FILE)
outputText = template.render()  # this is where to put args to the template renderer

print(outputText)

It turns out, the jinja2 API doc does have a section which discusses all the built-in loaders, so it's kind of embarrassing not to have noticed that right away. But the introduction is worded such that PackageLoader seems to be the default, "simplest" method. For newcomers to python, this can lead to a wild goose chase.

Solution 2 - Python

A simpler way is to directly call the jinj2.Template constructor and use open to load the file:

from jinja2 import Template
with open('template.html.jinja2') as file_:
    template = Template(file_.read())
template.render(name='John')

Solution 3 - Python

Here is the one liner:

from jinja2 import Template

with open('template_file.j2') as f:
    template = Template(f.read())

Then you can render the template on another line, or for all in one line:

with open('template_file.j2') as f:
    rendered = Template(f.read()).render(var="TEXT")

Solution 4 - Python

If using Python 3.4+ and Jinja2 - v2.11+ -- we can combine python's pathlib and Filesystem to simplify the flow

from pathlib import Path
...

p = Path(__file__).parent.parent / 'templates' # sample relative path
env = Environment(
    loader=FileSystemLoader(Path(p)))
template = env.get_template('your_file.jinja2')

I am not comfortable with using directly Template(file) since Jinja's template inheritance processing may not work well.

Pathlib support is only added in latest version of Jinja - v2.11+

Solution 5 - Python

from jinja2 import Environment, select_autoescape, FileSystemLoader

env = Environment(loader=FileSystemLoader(
searchpath=folder_contain_list_html), autoescape=select_autoescape(['html', 'xml']))

template = env.get_template('file_name_detail_template')

body_html = template.render(**args)

send_email(body_html)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJuan TomasView Question on Stackoverflow
Solution 1 - PythonJuan TomasView Answer on Stackoverflow
Solution 2 - PythonCasView Answer on Stackoverflow
Solution 3 - PythonbcarrollView Answer on Stackoverflow
Solution 4 - PythonSairam KrishView Answer on Stackoverflow
Solution 5 - PythonMarkView Answer on Stackoverflow