Est-il possible d'importer un module Python dans un modèle Jinja pour pouvoir utiliser ses fonctions?
Par exemple, j'ai un fichier format.py qui contient des méthodes de formatage des dates et des heures. Dans une macro Jinja, puis-je faire quelque chose comme comme suit?
{% from 'dates/format.py' import timesince %}
{% macro time(mytime) %}
<a title="{{ mytime }}">{{ timesince(mytime) }}</a>
{% endmacro %}
Parce que format.py n'est pas un modèle, le code ci-dessus me donne cette erreur:
UndefinedError: the template 'dates/format.py' (imported on line 2 in 'dates/macros.html') does not export the requested name 'timesince'
... mais je me demandais s'il y avait un autre moyen d'y parvenir.
Dans le modèle, non, vous ne pouvez pas importer de code python.
La façon de procéder consiste à enregistrer la fonction en tant que jinja2 filtre personnalisé , comme ceci:
Dans votre fichier python:
from dates.format import timesince
environment = jinja2.Environment(whatever)
environment.filters['timesince'] = timesince
# render template here
Dans votre modèle:
{% macro time(mytime) %}
<a title="{{ mytime }}">{{ mytime|timesince }}</a>
{% endmacro %}
Passez simplement la fonction dans le modèle, comme ça
from dates.format import timesince
your_template.render(timesince)
et dans le modèle, appelez-le comme n'importe quelle autre fonction,
{% macro time(mytime) %}
<a title="{{ mytime }}">{{ timesince(mytime) }}</a>
{% endmacro %}
Les fonctions sont des citoyens de première classe en python, vous pouvez donc les transmettre comme n'importe quoi d'autre. Vous pouvez même passer tout un module si vous le souhaitez.
Un modèle ne sait pas import
, mais vous pouvez l'enseigner avec importlib
:
import importlib
my_template.render( imp0rt = importlib.import_module ) # can't use 'import', because it's reserved
(vous pouvez également le nommer "import"
en passant l'argument avec un dict
)
kwargs = { 'import' : importlib.import_module }
my_template.render( **kwargs )
puis dans le jinja-template, vous pouvez importer n'importe quel module:
{% set time = imp0rt( 'time' ) %}
{{ time.time() }}
Vous pouvez exporter tous les symboles disponibles dans un module en fournissant les modules __dict__ en tant que paramètre à la méthode de rendu du modèle jinja. Les éléments suivants rendront disponibles les fonctions et les types de __builtin__, inspecteront et saisiront le module dans le modèle.
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)
Dans le modèle, pour utiliser une fonction des modules exportés similaire à la suivante:
{%- for element in getmembers(object) -%}
{# Use the getmembers function from inspect module on an object #}
{% endfor %}