Что это? Использование {{ }} в шаблонах

В языке Python имеется весьма полезный модуль Jinja (читается как дзиндзя – в честь японского синоитского святилища) служит для обработки шаблонов. Им можно пользоваться в своих собственных приложениях, но он также входит в состав множества других широко используемых модулей, например, Flask или Django. В рамках наших занятий мы рассмотрим основные возможности Jnija, которых, наверное, будет достаточно в 80%, а то и 90% случаях. Но, как всегда, полную и подробную информацию можно найти на официальном сайте:

https://jinja.palletsprojects.com/en/2.11.x/

Преимущество модуля Jinja в простоте использования и богатстве  предоставляемых возможностей для преобразования текстовых шаблонов. Но для начала нам потребуется его установить и, так как он входит в состав множества других пакетов, то возможно, у вас на компьютере он уже установлен. Попробуйте для начала выполнить вот такую простую программу на Python:

from jinja2 import Template
 
name = "Федор"
 
tm = Template("Привет {{ name }}")
msg = tm.render(name=name)
 
print(msg)

И если в консоли увидите строку:

Привет Федор

значит модуль Jinja готов к работе. Иначе, его следует установить с помощью команды:

pip install Jinja2

Итак, давайте внимательнее посмотрим, что делает эта программа. Сначала создается объект Template (шаблон), которому передается строка. В этой строке внутри двух фигурных скобок указана переменная name. Затем идет вызов метода render из этого объекта и передается именованный параметр name. В результате метод render будет ссылаться на словарь с ключом name и значением «Федор»:

{name: Федор}

Благодаря этому, вместо name будет в шаблоне подставлено значение «Федор», а метод render возвратит преобразованную строку.

Конечно, первая реакция: зачем так городить огород, когда все это можно сделать с помощью обычных F-строк Python:

msg2 = f"Привет {name}"
print(msg, msg2, sep="\n")

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

Итак, метод render класса Tempalte понимает следующие определения:

  • {% %} – спецификатор шаблона;
  • {{ }} – выражение для вставки конструкций Python в шаблон;
  • {# #} – блок комментариев;
  • # ## – строковый комментарий.

Только что мы видели на примере использование двух фигурных скобок. Давайте продолжим их изучение и немного усложним наш пример:

name = "Федор"
age = 28
 
tm = Template("Мне {{age}} лет и зовут {{ name }}.")
msg = tm.render(name=name, age=age)
 
print(msg)

Здесь все очень похоже на предыдущую программу, только используется два определения внутри шаблона с ключами age и name. Причем, значения ключей в методе render можно записывать в любом порядке. Кроме того, можно просто написать:

tm = Template("Мне {{a}} лет и зовут {{ n }}.")
msg = tm.render(n=name, a=age)

И все будет работать абсолютно также. То есть, здесь имя параметра – это ключ, вместо которого подставляется его значения при формировании выходной строки. Но, через этот ключ шаблон получает доступ к соответствующим переменным и может выполнять любые операции, известные в Python, например, так:

tm = Template("Мне {{a*2}} лет и зовут {{ n.upper() }}.")
msg = tm.render(a=age, n=name)

На выходе получим строку:

Мне 36 лет и зовут ФЕДОР.

Как видите, внутри двойных фигурных скобок можно использовать операторы языка Python.

Продолжим усложнять наш пример и, теперь предположим, что имеется класс:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

Затем, создается экземпляр этого класса:

per = Person("Федор", 33)

И необходимо информацию из него вывести в шаблоне. Это делается так:

tm = Template("Мне {{p.age}} лет и зовут {{ p.name }}.")
msg = tm.render(p=per)

Мы здесь передаем ссылку на объект класса Person и метод render берет имя и возраст из этого объекта, используя ссылку p. Или, если в классе Person реализовать геттеры:

    def getName(self):
        return self.name
 
    def getAge(self):
        return self.age

То в шаблоне можно вызвать их для получения необходимой информации:

tm = Template("Мне {{p. getAge()}} лет и зовут {{ p.getName() }}.")

Это еще раз показывает гибкость двойных фигурных скобок, в которых можно записывать любые (разумные для шаблона) операторы языка Python.

Ну, и наконец, передавать данные в шаблон можно непосредственно с помощью словаря. Например:

per = { 'name': 'Федор', 'age': 34 }
 
tm = Template("Мне {{p.age}} лет и зовут {{ p.name }}.")
msg = tm.render(p=per)

Или, можно обратиться к данным по такому синтаксису:

tm = Template("Мне {{p['age']}} лет и зовут {{ p['name'] }}.")

Результат будет одинаковым. Вот так используется определение двойные фигурные скобки в модуле Jinja.