So laden Sie die Jinja-Vorlage direkt aus dem Dateisystem

85

Das jinja API-Dokument auf pocoo.org lautet:

Die einfachste Möglichkeit, Jinja2 so zu konfigurieren, dass Vorlagen für Ihre Anwendung geladen werden, sieht ungefähr so ​​aus:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
Dadurch wird eine Vorlagenumgebung mit den Standardeinstellungen und einem Loader erstellt, der die Vorlagen im Vorlagenordner im Python-Paket Ihrer Anwendung nachschlägt .

Wie sich herausstellt, ist dies nicht so einfach, da Sie ein Python-Paket mit Ihren Vorlagen erstellen / installieren müssen, was eine Menge unnötiger Komplexität mit sich bringt, insbesondere wenn Sie nicht beabsichtigen, Ihren Code zu verteilen. Sie können hier und hier auf SO-Fragen zum Thema verweisen , aber die Antworten sind vage und unbefriedigend.

Was ein naiver Neuling natürlich tun möchte, ist, die Vorlage direkt aus dem Dateisystem zu laden, nicht als Ressource in einem Paket. Wie wird das gemacht?

Juan Tomas
quelle

Antworten:

124

So geht's : Verwenden Sie a FileSystemLoaderanstelle von a PackageLoader. Ich habe hier und hier Beispiele im Internet gefunden . Angenommen, Sie haben eine Python-Datei im selben Verzeichnis wie Ihre Vorlage:

./index.py
./template.html

Diese index.py findet die Vorlage und rendert sie:

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

Es stellt sich heraus, dass das jinja2-API-Dokument einen Abschnitt enthält, in dem alle integrierten Lader beschrieben werden. Es ist also etwas peinlich, das nicht sofort bemerkt zu haben. Die Einleitung ist jedoch so formuliert, dass PackageLoadersie die "einfachste" Standardmethode zu sein scheint. Für Python-Neulinge kann dies zu einer wilden Gänsejagd führen.

Juan Tomas
quelle
94
Irgendwie lächerlich, dass man eine Vorlage nicht aus einer Datei in einer Zeile laden kann, zBjinja2.load_template('template.html')
Matt
4
Ich habe immer einen Wrapper, den ich in meinen Anwendungen einfach Jinja2 nenne, wo ich all diese Ausführlichkeit einsetze, und dann wie folgt:Jinja2.render(template_name, data)
Seraf
11
Wichtiges Sicherheitsrisiko! Sie möchten mit ziemlicher Sicherheit anrufen jinja2.Environment(loader=templateLoader, autoescape=True). Oder lesen Sie die API-Dokumente für weitere Informationen. Ich habe gerade herausgefunden, dass ich aufgrund dieser Antwort eine große XSS-Sicherheitslücke hatte: /
andrewdotn
Beide Links oben sind defekt.
Show
76

Eine einfachere Möglichkeit besteht darin, den jinj2.TemplateKonstruktor direkt aufzurufen und opendie Datei zu laden:

from jinja2 import Template
with open('template.html.jinja2') as file_:
    template = Template(file_.read())
template.render(name='John')
Cas
quelle
1
Leider können hierdurch keine benutzerdefinierten Filter eingerichtet werden. Das Laden der Vorlage erzeugt während der Initialisierung einen Fehler, da der benutzerdefinierte Filter noch nicht vorhanden ist. Auf diese Weise haben Sie erst nach der Initialisierung Zugriff auf die Umgebung (einschließlich des Filters).
Ronan Paixão
17

Hier ist der eine Liner:

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

Anschließend können Sie die Vorlage in einer anderen Zeile oder für alle in einer Zeile rendern:

rendered = Template(open('template_file.j2').read()).render(var="TEXT")
bcarroll
quelle
1
Leider wird dies unterbrochen, wenn eine Vorlagenvererbung vorliegt, da Jinja die referenzierten Vorlagen nicht finden kann.
Bemmu
4
Aber zum Glück ist dies einfach und ausreichend, wenn Sie keine Vererbung verwenden und zum Beispiel keine einfache E-Mail senden möchten. :)
smido
3

Wenn Sie Python 3.4+ und Jinja2 - v2.11 + - verwenden, können Sie Pythons Pathlib und Dateisystem kombinieren, um den Ablauf zu vereinfachen

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

Ich bin mit der direkten Verwendung nicht zufrieden, Template(file)da Jinjas Vererbungsverarbeitung für Vorlagen möglicherweise nicht gut funktioniert.

Pathlib-Unterstützung wird nur in der neuesten Version von Jinja - v2.11 + hinzugefügt

Sairam Krish
quelle