web-dev-qa-db-fra.com

Importer un module Python dans un modèle Jinja?

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.

43
Matt Norris

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 %}
54
Wooble

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.

24
nightpool

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() }}
7
Skandix

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 %}
2
Simon Black