2011-01-28 18 views
31

¿Es posible importar un módulo Python en una plantilla Jinja para que pueda usar sus funciones?Importar un módulo Python en una plantilla Jinja?

Por ejemplo, tengo un archivo format.py que contiene métodos para formatear fechas y horas. En una macro Jinja, ¿puedo hacer algo como lo siguiente?

{% from 'dates/format.py' import timesince %} 

{% macro time(mytime) %} 
<a title="{{ mytime }}">{{ timesince(mytime) }}</a> 
{% endmacro %} 

Debido format.py no es una plantilla, el código anterior me da este error:

UndefinedError: the template 'dates/format.py' (imported on line 2 in 'dates/macros.html') does not export the requested name 'timesince' 

... pero me preguntaba si había otra manera de lograr esto.

Respuesta

42

Dentro de la plantilla, no, no puede importar el código de Python.

La manera de hacer esto es para registrar la función como Jinja2 custom filter, así:

En el archivo de Python:

from dates.format import timesince 

environment = jinja2.Environment(whatever) 
environment.filters['timesince'] = timesince 
# render template here 

En su plantilla:

{% macro time(mytime) %} 
<a title="{{ mytime }}">{{ mytime|timesince }}</a> 
{% endmacro %} 
16

Justo pasar la función a la plantilla, como

from dates.format import timesince 
your_template.render(timesince) 

y en la plantilla, a llamarlo como cualquier otra función,

{% macro time(mytime) %} 
    <a title="{{ mytime }}">{{ timesince(mytime) }}</a> 
{% endmacro %} 

Las funciones son ciudadanos de primera clase en Python, por lo que se pueden pasar en torno al igual que cualquier otra cosa. Incluso podría pasar un módulo completo si quisiera.

2

Puede exportar todos los símbolos disponibles en un módulo proporcionando los módulos __dict__ como un parámetro para el método de representación de la plantilla jinja. A continuación, se pondrán a disposición funciones y tipos de __builtin__, inspeccionarán y escribirán el módulo en la plantilla.

import __builtin__ 
import inspect 
import types 

env=RelEnvironment() 
template = env.get_template(templatefile) 

export_dict={} 
export_dict.update(__builtin__.__dict__) 
export_dict.update(types.__dict__) 
export_dict.update(inspect.__dict__) 

result=template.render(**export_dict) 

Dentro de la plantilla, para usar una función de los módulos exportados similar al siguiente:

{%- for element in getmembers(object) -%} 
{# Use the getmembers function from inspect module on an object #} 
{% endfor %} 
3

Una plantilla no sabe import, pero se puede enseñar con el importlib:

import importlib 
my_template.render(imp0rt = importlib.import_module) # can't use 'import', because it's reserved 

(también puede llamarlo "import" pasando el argumento con un dict)

kwargs = { 'import' : importlib.import_module } 
my_template.render(**kwargs) 

continuación, en el Jinja-plantilla, puede importar cualquier módulo:

{% set time = imp0rt('time') %} 
{{ time.time() }} 
Cuestiones relacionadas