如何直接从文件系统加载 jinja 模板

How to load jinja template directly from filesystem

jinja API document at pocoo.org 状态:

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.

事实证明,这并不是那么简单,因为您必须 make/install 一个包含模板的 python 包,这会带来很多不必要的复杂性,尤其是如果您有无意分发您的代码。您可以参考关于here and 主题的SO问题,但答案含糊不清。

天真的新手想要做的,显然只是直接从文件系统加载模板,而不是作为包中的资源。 这是怎么做到的?

方法如下:使用 FileSystemLoader 而不是 PackageLoader。我在网上找到了示例 here and here。假设您在与模板相同的目录中有一个 python 文件:

./index.py
./template.html

这 index.py 将找到模板并呈现它:

#!/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)

事实证明,jinja2 API 文档确实有一个 section which discusses all the built-in loaders,所以没有立即注意到这一点有点尴尬。但是介绍的措辞使得 PackageLoader 似乎是默认的 "simplest" 方法。对于 python 的新手来说,这可能会导致一场徒劳的追逐。

更简单的方法是直接调用jinj2.Template构造函数,使用open加载文件:

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

这是一个班轮:

from jinja2 import Template

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

然后你可以在另一行渲染模板,或者在一行中渲染所有模板:

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

如果使用 Python 3.4+ 和 Jinja2 - v2.11+ -- 我们可以结合 python 的路径库和文件系统来简化流程

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')

我不习惯直接使用Template(file),因为 Jinja 的模板继承处理可能效果不佳。

仅在最新版本的 Jinja - v2.11+ 中添加了 Pathlib 支持

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)