Как загрузить шаблон jinja прямо из файловой системы


87

В документе API jinja на pocoo.org говорится:

Самый простой способ настроить Jinja2 для загрузки шаблонов для вашего приложения выглядит примерно так:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
Это создаст среду шаблонов с настройками по умолчанию и загрузчик, который будет искать шаблоны в папке шаблонов внутри пакета python yourapplication .

Как оказалось, это не так просто, потому что вам нужно создать / установить пакет python с вашими шаблонами в нем, что вносит много ненужной сложности, особенно если вы не собираетесь распространять свой код. Вы можете обратиться к SO-вопросам по теме здесь и здесь , но ответы расплывчаты и неудовлетворительны.

Очевидно, что наивный новичок просто загружает шаблон непосредственно из файловой системы, а не как ресурс в пакете. Как это сделать?

Ответы:


129

Вот как : используйте FileSystemLoaderвместо 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)

Оказывается, в документации API jinja2 есть раздел, в котором обсуждаются все встроенные загрузчики , так что неловко не заметить это сразу. Но введение сформулировано так, что PackageLoaderкажется "простейшим" методом по умолчанию. Для новичков в питоне это может привести к охоте на диких гусей.


96
Вроде смешно, что нельзя загрузить шаблон из файла в одну строку, напримерjinja2.load_template('template.html')
Мэтт

4
У меня всегда есть Wrapper, который я просто называю Jinja2 в своих приложениях, где я помещаю всю эту многословность, а затем называю это так:Jinja2.render(template_name, data)
Сераф

11
Важная угроза безопасности! Вы почти наверняка захотите позвонить jinja2.Environment(loader=templateLoader, autoescape=True). Или см. Документацию по API для получения дополнительной информации. Только что узнал, что я получил серьезную XSS-уязвимость, следуя этому ответу: /
andrewdotn

Обе ссылки вверху не работают.
sshow

77

Более простой способ - напрямую вызвать jinj2.Templateконструктор и использовать его openдля загрузки файла:

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

1
К сожалению, это не позволяет настраивать собственные фильтры. При загрузке шаблона возникает ошибка во время инициализации, поскольку настраиваемый фильтр еще не существует. Таким образом, у вас будет доступ к среде (для включения фильтра) только после инициализации.
Ronan Paixão

18

Вот один лайнер:

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

Затем вы можете отобразить шаблон в другой строке или для всех в одной строке:

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

1
К сожалению, это сломается, если существует наследование шаблонов, поскольку Jinja не сможет найти шаблоны, на которые есть ссылки.
Bemmu

4
Но, к счастью, это просто и достаточно, если вы не используете наследование и просто не хотите, например, отправлять простое электронное письмо .. :)
smido

5

При использовании Python 3.4+ и Jinja2 - v2.11 + - мы можем объединить pathlib и файловую систему 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 может работать некорректно.

Поддержка Pathlib добавлена ​​только в последней версии Jinja - v2.11 +

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.