Вызов функции Python из jinja2 - PullRequest
121 голосов
/ 17 мая 2011

Я использую jinja2 и хочу вызвать функцию python в качестве помощника, используя такой же синтаксис, как если бы я вызывал макрос.jinja2, похоже, намерен помешать мне сделать вызов функции, и настаивает на том, чтобы я повторил себя, скопировав функцию в шаблон в виде макроса.

Есть ли простой способ сделать это?И есть ли способ импортировать целый набор функций Python и сделать их доступными из jinja2, не проходя через множество ригамаролей (таких как написание расширения)?

Ответы [ 11 ]

197 голосов
/ 29 августа 2011

Для тех, кто использует Flask, укажите это в вашем __init__.py:

def clever_function():
    return u'HELLO'

app.jinja_env.globals.update(clever_function=clever_function)

и в вашем шаблоне назовите его с помощью {{ clever_function() }}

109 голосов
/ 09 апреля 2014

Примечание: это колба!

Я знаю, что этот пост довольно старый, но есть более эффективные способы сделать это в более новых версиях Flask с использованием контекстных процессоров.

Переменные могут быть легко созданы:

@app.context_processor
def example():
    return dict(myexample='This is an example')

Вышесказанное можно использовать в шаблоне Jinja2 с Flask, например:

{{ myexample }}

(Какие выходы This is an example)

А также полноценные функции:

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

Вышеуказанное при использовании выглядит так:

{{ format_price(0.33) }}

(который выводит входную цену с символом валюты)

В качестве альтернативы вы можете использовать фильтры дзиндзя , выпекаемые во фляге. Например. с использованием декораторов:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

Или без декораторов и вручную регистрируя функцию:

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

Фильтры, применяемые двумя вышеупомянутыми методами, могут использоваться следующим образом:

{% for x in mylist | reverse %}
{% endfor %}
70 голосов
/ 18 мая 2011

Я думаю, что jinja намеренно затрудняет запуск «произвольного» питона в шаблоне.Он пытается навязать мнение, что меньше логики в шаблонах - это хорошо.

Вы можете манипулировать глобальным пространством имен в экземпляре Environment, чтобы добавлять ссылки на ваши функции.Это должно быть сделано до загрузки любых шаблонов.Например:

from jinja2 import Environment, FileSystemLoader

def clever_function(a, b):
    return u''.join([b, a])

env = Environment(loader=FileSystemLoader('/path/to/templates'))
env.globals['clever_function'] = clever_function
37 голосов
/ 24 ноября 2014
from jinja2 import Template

def custom_function(a):
    return a.replace('o', 'ay')

template = Template('Hey, my name is {{ custom_function(first_name) }} {{ func2(last_name) }}')
template.globals['custom_function'] = custom_function

Вы также можете задать функцию в полях согласно Ответу Матроскина

fields = {'first_name': 'Jo', 'last_name': 'Ko', 'func2': custom_function}
print template.render(**fields)

Будет выводиться:

Hey, my name is Jay Kay

Работает с версией Jinja22.7.3

И если вы хотите, чтобы декоратор упростил определение функций в template.globals, проверьте Ответ Бруно Броноски

16 голосов
/ 14 ноября 2017

Мне нравится @ ответ AJP .Я использовал его дословно, пока у меня не появилось много функций.Затем я переключился на декоратор функций Python .

from jinja2 import Template

template = '''
Hi, my name is {{ custom_function1(first_name) }}
My name is {{ custom_function2(first_name) }}
My name is {{ custom_function3(first_name) }}
'''
jinga_html_template = Template(template)

def template_function(func):
    jinga_html_template.globals[func.__name__] = func
    return func

@template_function
def custom_function1(a):
    return a.replace('o', 'ay')

@template_function
def custom_function2(a):
    return a.replace('o', 'ill')

@template_function
def custom_function3(a):
    return 'Slim Shady'

fields = {'first_name': 'Jo'}
print(jinga_html_template.render(**fields))

Хорошие функции имеют __name__!

11 голосов
/ 10 августа 2017

Никогда не видел такой простой способ на официальных документах или при переполнении стека, но я был поражен, когда нашел это:

# jinja2.__version__ == 2.8
from jinja2 import Template

def calcName(n, i):
    return ' '.join([n] * i)

template = Template("Hello {{ calcName('Gandalf', 2) }}")

template.render(calcName=calcName)
# or
template.render({'calcName': calcName})
9 голосов
/ 24 июля 2014

Используйте лямбду для подключения шаблона к основному коду

return render_template("clever_template", clever_function=lambda x: clever_function x)

Тогда вы можете без проблем вызвать функцию в шаблоне

{{clever_function(value)}}
5 голосов
/ 21 апреля 2016

Чтобы вызвать функцию Python из Jinja2, вы можете использовать пользовательские фильтры, которые работают так же, как и глобальные: http://jinja.pocoo.org/docs/dev/api/#writing-filters

Это довольно просто и полезно. В файле myTemplate.txt я написал:

{{ data|pythonFct }}

И в скрипте Python:

import jinja2

def pythonFct(data):
    return "This is my data: {0}".format(data)

input="my custom filter works!"

loader = jinja2.FileSystemLoader(path or './')
env = jinja2.Environment(loader=loader)
env.filters['pythonFct'] = pythonFct
result = env.get_template("myTemplate.txt").render(data=input)
print(result)
4 голосов
/ 09 октября 2017

Есть ли способ импортировать весь набор функций Python и сделать их доступными из jinja2?

Да, в дополнение к другим ответам выше, это работает для меня.

Создайте класс и заполните его связанными методами, например

class Test_jinja_object:

    def __init__(self):
        self.myvar = 'sample_var'

    def clever_function (self):
        return 'hello' 

Затем создайте экземпляр вашего класса в вашей функции представления и передайте полученный объект вашему шаблону в качестве параметра для функции render_template

my_obj = Test_jinja_object()

Теперь в вашем шаблоне вы можете вызывать методы класса в jinja следующим образом:

{{ my_obj.clever_function () }}
3 голосов
/ 19 февраля 2018

Для импорта всех встроенных функций вы можете использовать:

app.jinja_env.globals.update(__builtins__)

Добавьте .__dict__ после __builtins__, если это не работает.

Основано на ответе John32323 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...