Перейти к содержанию

Расширение возможностей шаблонов

Мы прошлись по основным возможностям языка шаблонов Jinja. Но сама технология дает больше возможностей чем мы изучили на текущий момент. О некоторых из них в этом уроке.

Доступ к методам Python объектов

Объекты, которые вы передаете в контексте выполнения шаблонов это python объекты. Они имеют свои методы и Jinja дает возможность с ними работать. Например, у строковой переменной есть метод .capialize(). Его можно использовать:

{{ page.title.capitalize() }}

Правда конкретно для этого примера уже есть фильтр, который тоже имеет такое же имя.

{{ page.title|capitalize }}

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

from datetime import datetime
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def frontpage():
    return render_template("index.html", now=datetime.now())

Теперь в шаблоне можно использовать методы объекта (index.html):

...
<h2>Дата {{ now.isoformat() }}</h2>
...

Добавление своих функций

Jinja можно расширять с помощью добавления своих функций. Самый простой способ — это передать функцию в качестве контекста. Этот способ является логическим продолжением предыдущего примера.

from datetime import datetime
from flask import Flask, render_template

app = Flask(__name__)

def hello(name):
    return f"Привет, {name}!"

@app.route("/")
def frontpage():
    return render_template("index.html", hello=hello)

И в коде шаблона:

...
<strong>{{ hello('Пользователь') }}</strong>
...

Глобальные функции и фильтры с помощью Flask

Передавать удобную функцию в коде каждый раз очень неудобно, поэтому Flask предоставляет централизированный способ регистрации функций:

@app.context_processor
def utility_processor():
    def format_price(amount, currency="€"):
        return f"{amount:.2f}{currency}"
    return dict(format_price=format_price)

Теперь функция format_price будет доступна внутри всех шаблонов проекта:

{{ format_price(0.33) }}

Обратите внимание, что context_processor ждет на выходе словарь. Внутри словаря могут находиться любые значения, не обязательно функции. Удобно объединять вместе часто используемые объекты.

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

# Способ 1: с помощью декоратора
@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

# Способ 2: напрямую используя конфигуратор окружения
def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

Этот фильтр инверсирует список или строку:

{% for x in mylist | reverse %}
  Значение {{ x }}
{% endfor %}

{{ value | reverse }}

Flask активно пользуется этими возможностями и самостоятельно добавляет некоторые функции и объекты. Мы с этим познакомимся подробнее.