Я использую jinja2 и хочу вызвать функцию python в качестве помощника, используя такой же синтаксис, как если бы я вызывал макрос. jinja2, похоже, намерен помешать мне выполнить вызов функции и настаивает, чтобы я повторял себя, копируя функцию в шаблон в виде макроса.
Есть ли простой способ сделать это? И есть ли способ импортировать весь набор функций Python и сделать их доступными из jinja2, не проходя через целую кучу ритуалов (например, написание расширения)?
from jinja2 import Template ##newline## def clever_function(): ##newline## return "Hello" ##newline## template = Template("{{ clever_function() }}") ##newline## print(template.render(clever_function=clever_function))
Примечание: это специфично для Flask!
Я знаю, что этот пост довольно старый, но в новых версиях Flask есть более эффективные способы сделать это с использованием контекстных процессоров.
Переменные можно легко создавать:
@app.context_processor def example(): return dict(myexample='This is an example')
Вышеупомянутое можно использовать в шаблоне Jinja2 с Flask следующим образом:
(Какие выходы
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 %}
источник
__init__.py
предполагая, что выflask.Flask(__name__)
там заявили .Я думаю, что 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
источник
import utils.helpers env.globals['helpers'] = utils.helpers
{{ clever_function('a', 'b') }}
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
Работает с Jinja2 версии 2.7.3
И если вы хотите, чтобы декоратор облегчил определение функций
template.globals
, ознакомьтесь с ответом Бруно Броноски.источник
Мне нравится ответ @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__
!источник
Никогда не видел такого простого способа в официальных документах или при переполнении стека, но я был поражен, когда обнаружил это:
# 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})
источник
Используйте лямбда, чтобы подключить шаблон к вашему основному коду
return render_template("clever_template", clever_function=lambda x: clever_function x)
Затем вы можете легко вызвать функцию в шаблоне
источник
Чтобы вызвать функцию Python из Jinja2, вы можете использовать настраиваемые фильтры, которые работают так же, как глобальные: http://jinja.pocoo.org/docs/dev/api/#writing-filters
Это довольно просто и полезно. В файле myTemplate.txt я написал:
И в скрипте 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)
источник
есть ли способ импортировать весь набор функций python и сделать их доступными из jinja2?
Да, есть, в дополнение к другим ответам выше, это работает для меня.
Создайте класс и заполните его соответствующими методами, например
class Test_jinja_object: def __init__(self): self.myvar = 'sample_var' def clever_function (self): return 'hello'
Затем создайте экземпляр своего класса в своей функции просмотра и передайте полученный объект в свой шаблон в качестве параметра для функции render_template.
Теперь в вашем шаблоне вы можете вызывать методы класса в jinja следующим образом
источник
Чтобы импортировать все встроенные функции, вы можете использовать:
Добавьте
.__dict__
после,__builtins__
если это не сработает.На основе ответа John32323 .
источник
Если вы делаете это с помощью Django, вы можете просто передать функцию с контекстом:
context = { 'title':'My title', 'str': str, } ... return render(request, 'index.html', context)
Теперь вы сможете использовать
str
функцию в шаблоне jinja2источник
Есть гораздо более простое решение.
@app.route('/x') def x(): return render_template('test.html', foo=y) def y(text): return text
Затем в test.html :
{{ y('hi') }}
источник
Ответ @ John32323 - очень чистое решение.
Вот такой же, но сохраните в отдельный файл, может быть, более чистый.
Создать вспомогательный файл
приложение \ helper.py
from app import app def clever_function_1(): return u'HELLO' def clever_function_2(a, b): return a + b app.jinja_env.globals.update( clever_function_1=clever_function_1, clever_function_2=clever_function_2, )
Импортировать из приложения
app.py
from app import routes from app import helper # add this one
Используйте как это
приложение \ шаблоны \ some.html
источник