Подтвердить что ты не робот

Вызовите функцию python из jinja2

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

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

4b9b3361

Ответ 1

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

def clever_function():
    return u'HELLO'

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

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

Ответ 2

Примечание. Это флажок специфический!

Я знаю, что этот пост довольно старый, но есть лучшие способы сделать это в новых версиях 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) }}

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

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

@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 %}

Ответ 3

Я думаю, что 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

Ответ 4

from jinja2 import Template

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

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

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

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

Hey, my name is Jay

Работает с версией Jinja2 2.7.3

Ответ 5

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

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

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

{{clever_function(value)}}

Ответ 6

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

# 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})

Ответ 7

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

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

{{ data|pythonFct }}

И в python script:

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)

Ответ 8

Если вы делаете это с Django, вы можете просто передать функцию с контекстом:

context = {
    'title':'My title',
    'str': str,
}
...
return render(request, 'index.html', context)

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

Ответ 9

Есть ли способ импортировать весь набор функций 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 () }}

Ответ 10

Мне нравится @AJP answer. Я использовал его дословно, пока у меня не было много функций. Затем я переключился на декоратор функций 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__!