Cómo cargar la plantilla jinja directamente desde el sistema de archivos

85

El documento de la API de jinja en pocoo.org dice:

La forma más sencilla de configurar Jinja2 para cargar plantillas para su aplicación se ve más o menos así:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
Esto creará un entorno de plantilla con la configuración predeterminada y un cargador que mira hacia arriba en las plantillas de las plantillas de la carpeta dentro de la yourapplication paquete python.

Resulta que esto no es tan simple porque tiene que crear / instalar un paquete de Python con sus plantillas, lo que introduce mucha complejidad innecesaria, especialmente si no tiene la intención de distribuir su código. Puede consultar las preguntas SO sobre el tema aquí y aquí , pero las respuestas son vagas e insatisfactorias.

Lo que un novato ingenuo quiere hacer, obviamente, es simplemente cargar la plantilla directamente desde el sistema de archivos, no como un recurso en un paquete. ¿Cómo se hace esto?

Juan Tomás
fuente

Respuestas:

124

He aquí cómo : use a en FileSystemLoaderlugar de a PackageLoader. Encontré ejemplos en la web aquí y aquí . Digamos que tiene un archivo de Python en el mismo directorio que su plantilla:

./index.py
./template.html

Este index.py encontrará la plantilla y la renderizará:

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

Resulta que el documento de la API jinja2 tiene una sección que analiza todos los cargadores integrados , por lo que es un poco vergonzoso no haberlo notado de inmediato. Pero la introducción está redactada de tal manera que PackageLoaderparece ser el método "más simple" predeterminado. Para los recién llegados a Python, esto puede conducir a una persecución inútil.

Juan Tomás
fuente
94
Algo ridículo, no puede cargar una plantilla de un archivo en una línea, por ejemplojinja2.load_template('template.html')
Matt
4
Siempre tengo un Wrapper que llamo Jinja2 en mis aplicaciones donde pongo toda esta verbosidad, luego lo llamo así:Jinja2.render(template_name, data)
Seraf
11
¡Riesgo de seguridad importante! Es casi seguro que quieras llamar jinja2.Environment(loader=templateLoader, autoescape=True). O consulte los documentos de la API para obtener más información. Acabo de descubrir que terminé con una vulnerabilidad XSS importante al seguir esta respuesta: /
andrewdotn
Ambos enlaces en la parte superior están rotos.
Mostrar el
76

Una forma más sencilla es llamar directamente al jinj2.Templateconstructor y usar openpara cargar el archivo:

from jinja2 import Template
with open('template.html.jinja2') as file_:
    template = Template(file_.read())
template.render(name='John')
Cas
fuente
1
Desafortunadamente, esto no permite configurar filtros personalizados. La carga de la plantilla genera un error durante la inicialización porque el filtro personalizado aún no existe. Y de esta manera solo tiene acceso al entorno (para incluir el filtro) después de la inicialización.
Ronan Paixão
17

Aquí está el delineador:

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

Luego, puede representar la plantilla en otra línea o para todo en una línea:

rendered = Template(open('template_file.j2').read()).render(var="TEXT")
bcarroll
fuente
1
Lamentablemente, esto se romperá si hay herencia de plantillas, ya que Jinja no podrá encontrar las plantillas a las que se hace referencia.
Bemmu
3
Pero afortunadamente, esto es simple y suficiente si no usa la herencia, y simplemente no quiere enviar un correo electrónico simple, por ejemplo .. :)
smido
2

Si usamos Python 3.4+ y Jinja2 - v2.11 + - podemos combinar Pathlib y Filesystem de Python para simplificar el flujo

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

No me siento cómodo usándolo directamente Template(file)ya que el procesamiento de herencia de plantillas de Jinja puede no funcionar bien.

La compatibilidad con Pathlib solo se agrega en la última versión de Jinja - v2.11 +

Sairam Krish
fuente