2011-01-28 6 views
31

È possibile importare un modulo Python in un modello Jinja in modo che io possa utilizzare le sue funzioni?Importare un modulo Python in un modello Jinja?

Ad esempio, ho un file format.py che contiene metodi per la formattazione di date e orari. In una macro Jinja, posso fare qualcosa come quanto segue?

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

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

Perché format.py non è un modello, il codice di cui sopra mi dà questo errore:

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

... ma mi chiedevo se ci fosse un altro modo per raggiungere questo obiettivo.

risposta

42

all'interno del modello, no, non è possibile importare codice Python.

Il modo per farlo è quello di registrare la funzione di Jinja2 custom filter, in questo modo:

Nel file python:

from dates.format import timesince 

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

Nel modello:

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

Proprio passare la funzione nel modello, in questo modo

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

e nel modello, lo chiamano semplicemente come qualsiasi altra funzione,

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

Le funzioni sono cittadini di prima classe in Python, in modo da poterli passare in giro, proprio come qualsiasi altra cosa. Potresti anche passare in un intero modulo se lo volessi.

2

È possibile esportare tutti i simboli disponibili in un modulo, fornendo i moduli __dict__ come parametro per il modello di Jinja metodo Render. Quanto segue renderà disponibili funzioni e tipi di __builtin__, inspect e types module al template.

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) 

All'interno del modello, da utilizzare in funzione dei moduli esportati simile al seguente:

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

Un modello non sa import, ma si può insegnare con il importlib:

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

(è anche possibile denominarlo "import" passando l'argomento con un dict)

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

poi in Jinja-modello, è possibile importare qualsiasi modulo:

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