Jak załadować szablon jinja bezpośrednio z systemu plików

85

Dokument jinja API na pocoo.org stwierdza:

Najprostszy sposób skonfigurowania Jinja2 do ładowania szablonów dla twojej aplikacji wygląda mniej więcej tak:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
Spowoduje to utworzenie środowiska szablonów z domyślnymi ustawieniami i programem ładującym, który wyszukuje szablony w folderze szablonów w pakiecie python aplikacji yourapplication .

Jak się okazuje, nie jest to takie proste, ponieważ musisz stworzyć / zainstalować pakiet Pythona ze swoimi szablonami, co wprowadza dużo niepotrzebnej złożoności, zwłaszcza jeśli nie masz zamiaru dystrybuować swojego kodu. Możesz odnieść się do pytań SO na ten temat tutaj i tutaj , ale odpowiedzi są niejasne i niezadowalające.

Naiwny początkujący chce oczywiście po prostu załadować szablon bezpośrednio z systemu plików, a nie jako zasób w pakiecie. Jak to się robi?

Juan Tomas
źródło

Odpowiedzi:

124

Oto jak : użyj a FileSystemLoaderzamiast a PackageLoader. Znalazłem przykłady w sieci tutaj i tutaj . Powiedzmy, że masz plik Pythona w tym samym katalogu co szablon:

./index.py
./template.html

Ten plik index.py znajdzie szablon i wyrenderuje go:

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

Okazuje się, że dokumentacja jinja2 API ma sekcję, która omawia wszystkie wbudowane programy ładujące , więc jest trochę żenujące, że nie zauważyłem tego od razu. Ale wprowadzenie jest sformułowane w taki sposób, że PackageLoaderwydaje się być domyślną, „najprostszą” metodą. Dla nowicjuszy w Pythonie może to prowadzić do dzikiej pogoni za gęsi.

Juan Tomas
źródło
94
To trochę śmieszne, że nie można załadować szablonu z pliku w jednej linii, np.jinja2.load_template('template.html')
Matt,
4
Zawsze mam Wrapper, który po prostu nazywam Jinja2 w moich aplikacjach, w których umieszczam całą tę gadatliwość, a następnie nazywam to:Jinja2.render(template_name, data)
Seraf
11
Poważne zagrożenie bezpieczeństwa! Prawie na pewno chcesz zadzwonić jinja2.Environment(loader=templateLoader, autoescape=True). Aby uzyskać więcej informacji, zapoznaj się z dokumentacją API . Właśnie dowiedziałem się, że mam poważną lukę w zabezpieczeniach XSS po wykonaniu tej odpowiedzi: /
andrewdotn
Oba łącza u góry są uszkodzone.
pokaż
76

Prostszym sposobem jest bezpośrednie wywołanie jinj2.Templatekonstruktora i użycie go opendo załadowania pliku:

from jinja2 import Template
with open('template.html.jinja2') as file_:
    template = Template(file_.read())
template.render(name='John')
Cas
źródło
1
Niestety nie pozwala to na ustawienie niestandardowych filtrów. Ładowanie szablonu generuje błąd podczas inicjalizacji, ponieważ niestandardowy filtr jeszcze nie istnieje. W ten sposób dostęp do środowiska (w tym filtra) masz dopiero po inicjalizacji.
Ronan Paixão,
17

Oto jedna wkładka:

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

Następnie możesz wyrenderować szablon w innej linii lub dla wszystkich w jednej linii:

rendered = Template(open('template_file.j2').read()).render(var="TEXT")
bcarroll
źródło
1
Niestety, to się zepsuje, jeśli istnieje dziedziczenie szablonów, ponieważ Jinja nie będzie w stanie znaleźć szablonów, do których istnieją odniesienia.
Bemmu
4
Ale na szczęście jest to proste i wystarczające, jeśli nie używasz dziedziczenia, a po prostu nie chcesz na przykład wysłać prostego e-maila .. :)
smido
3

Jeśli używasz Pythona 3.4+ i Jinja2 - v2.11 + - możemy połączyć pathlib i Filesystem Pythona, aby uprościć przepływ

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

Nie czuję się komfortowo w używaniu bezpośrednio, Template(file)ponieważ przetwarzanie dziedziczenia szablonów Jinja może nie działać dobrze.

Obsługa Pathlib jest dodana tylko w najnowszej wersji Jinja - v2.11 +

Sairam Krish
źródło