В языке 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.