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


85

pocoo.org上jinja API文档指出:

配置Jinja2为应用程序加载模板的最简单方法大致如下:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
这将使用默认设置创建一个模板环境,并使用一个加载器在yourapplication python包内的templates文件夹中查找模板。

事实证明,这并不是那么简单,因为您必须制作/安装带有模板的python软件包,这引入了很多不必要的复杂性,尤其是在您无意分发代码的情况下。您可以在此处此处参考有关该主题的SO问题,但是答案是含糊不清和不令人满意的。

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

Answers:


124

方法如下:使用aFileSystemLoader代替a PackageLoader。我在这里这里的网上都找到了示例。假设您在与模板相同的目录中有一个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文档中确实有一节讨论了所有内置的加载器,因此如果没有立即注意到这一点就有些尴尬。但是引言的措辞PackageLoader似乎是默认的“最简单”方法。对于python的新手来说,这可能会导致人们大肆追逐。


94
有点荒谬,您无法在一文件中从文件中加载模板,例如jinja2.load_template('template.html')
Matt

4
我总是有一个包装程序,在我的应用程序中只是将Jinja2放在其中,我将所有这些详细信息放在其中,然后像这样称呼它:Jinja2.render(template_name, data)
Seraf

11
重要的安全风险!您几乎肯定要打电话jinja2.Environment(loader=templateLoader, autoescape=True)。或参阅api文档了解更多信息。刚发现,按照以下答案,我最终遇到了一个主要的XSS漏洞:/
andrewdotn '19

顶部的两个链接都断开了。
表演

76

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

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

1
不幸的是,这不允许设置自定义过滤器。由于自定义过滤器尚不存在,因此模板加载在初始化期间会产生错误。这样,您只能在初始化后访问环境(包括过滤器)。
RonanPaixão19年

17

这是一个班轮:

template = Template(open('template_file.j2').read())

然后,您可以在另一行上渲染模板,也可以在一行上渲染模板:

rendered = Template(open('template_file.j2').read()).render(var="TEXT")

1
遗憾的是,如果存在模板继承,这将中断,因为Jinja无法找到引用的模板。
Bemmu

3
但是幸运的是,这很简单,如果您不使用继承,就足以发送一些简单的电子邮件了。..:)
smido

2

如果使用Python 3.4+和Jinja2-v2.11 +-我们可以结合使用python的pathlib和Filesystem来简化流程

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支持

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.