Jinja2
Материал из Xgu.ru
Jinja2 (Jinja) — язык шаблонов, использующийся в Python.
Jinja используется для генерации текстовых файлов на основе одного или нескольких шаблонов.
В результате обработки шаблона, Jinja может сгенерировать файл в любом текстовом формате:
- HTML
- CSV
- LaTeX
- и другие
Jinja это не единственный язык шаблонов (шаблонизатор) для Python и, конечно же, не единственный язык шаблонов в целом.
Содержание |
[править] Основы интерфейса Jinja
Шаблон Jinja это обычный текстовый файл, в котором, с помощью различных выражений, можно указать какие значения в шаблоне должны быть заменены.
Кроме выражений, в шаблоне могут быть, например, различные конструкции, которые управляют логикой обработки данных, при формировании документа по шаблону.
Пример шаблона:
Hello {{name}}!
По умолчанию, переменные (а точнее, выражения) записываются в Jinja в двойных фигурных скобках. Например, в этом шаблоне есть переменная: name.
Самый базовый способ создания шаблона и его обработки это использование класса Template:
In [1]: from jinja2 import Template In [2]: template = Template("Hello {{name}}!") In [3]: print(template.render(name='Nick')) Hello Nick!
Создав экземпляр Template, мы получаем новый объект, у которого есть метод render(). Этот метод обрабатывает шаблон, используя словарь или именованные аргументы, которые ему передаются.
Словарь или именованные аргументы, которые передаются шаблону, это, так называемый, контекст шаблона.
[править] Программный интерфейс
В этом разделе описывается программный интерфейс для работы с Jinja. Язык шаблонов описывается ниже.
[править] Loaders (загрузчики)
Загрузчики отвечают за загрузку шаблонов из различных источников, например, из файловой системы.
В Jinja есть несколько встроенных загрузчиков. Но можно создать и свой собственный загрузчик.
[править] FileSystemLoader
FileSystemLoader - это загрузчик, который позволяет загружать шаблоны из файловой системы.
Этот загрузчик ищет шаблоны в каталогах файловой системы и является предпочтительным способом загружать шаблоны.
При создании загрузчика FileSystemLoader, надо указать путь к шаблонам: путь указывается как строка или, если есть несколько путей, то указывается список путей:
loader = FileSystemLoader('/projects/project1/templates') loader = FileSystemLoader(['/personal_projects/pro1/templates', '/work_projects/auto/templates'])
В загрузчика также можно указывать кодировку. По умолчанию кодировка 'utf-8'.
loader = FileSystemLoader('/projects/project1/templates', encoding='utf-8')
Для того чтобы загрузчик следовал по символическим ссылкам, надо указать параметр followlinks (по умолчанию False):
loader = FileSystemLoader('/projects/project1/templates', followlinks=True)
[править] Environment (окружение)
Экземпляры класса Environment:
- используются для хранения конфигурации и глобальных объектов
- используются для загрузки шаблонов из файловой системы или других местоположений
- при создании шаблонов из строк, с помощью конструктора класса Template, окружение создается автоматически
Пример задания окружения для загрузки шаблонов:
from jinja2 import Environment, FileSystemLoader loader = FileSystemLoader('/project1/templates') env = Environment(loader, trim_blocks=True, lstrip_blocks=True)
В окружении указаны:
- загрузчик FileSystemLoader и путь, в котором следует искать шаблоны
- дополнительные параметры окружения определяют как работать с шаблонами:
- trim_blocks - если установлено в True, удаляет первую пустую строку после блока конструкции (по умолчанию False)
- lstrip_blocks - если установлено в True, пробелы и табы в начале строки удаляются (по умолчанию False)
[править] Методы Environment
get_template - это метод, который позволяет загрузить шаблон из загрузчика:
- Если загрузчик существует, этот метод запрашивает шаблон у загрузчика и возвращает Template()
- Если загрузчика нет, отображается исключение TemplateNotFound
[править] Пример использования программного интерфейса для загрузки шаблона
Файл html_template с шаблоном HTML:
<head> <title>{{ title }}</title> </head> <body> <h1>{{ header_1 }}</h1> {% for link in links %} <li><a href="{{ link[link] }}">{{ link }}</a></li> {% endfor %} </body>
Скрипт для генерации документа из шаблона (html_generate.py):
from jinja2 import Environment, FileSystemLoader loader = FileSystemLoader('/projects/jinja2') env = Environment(loader, trim_blocks=True, lstrip_blocks=True) template = env.get_template('html_template') html_links = {'Main Page':'http://xgu.ru', 'Jinja':'http://xgu.ru/wiki/Jinja2'} data = {'title':'Site information','header_1':'Popular pages','links':html_links} with open("new.html", "w") as f: f.write(template.render(data))
Результат:
natasha$ python html_generate.py natasha$ cat new.html <head> <title>Site information</title> </head> <body> <h1>Popular pages</h1> <li><a href="http://xgu.ru">Main Page</a></li> <li><a href="http://xgu.ru/wiki/Jinja2">Jinja</a></li> </body>
[править] jinja2.Template()
Класс Template() - это основной объект, который представляет скомпилированный шаблон и используется для его обработки.
Объект Template() можно получить такими способами:
- сгенерировать его из окружения
- создать объект используя конструктор (вариант, который использовался выше)
Шаблон - это неизменяемый объект.
В каждом шаблоне есть несколько методов. Значения методов генирируются по-разному для шаблона, который был создан с помощью конструктора и для шаблона, который был сгенерирован из окружения.
[править] Методы шаблона
Методы шаблонов показаны в ipython на примере двух шаблонов.
Шаблон template1 создан с помощью конструктора:
In [1]: import jinja2 In [2]: template1 = jinja2.Template('Hello {{name}}!')
Шаблон template2 взят из предыдущего примера:
In [3]: ls html_generate.py html_generate.pyc html_templates/ new.html In [4]: from html_generate import template as template2
Метод name - отображает имя шаблона. Если шаблон был загружен из строки, имя равно None:
In [6]: print template1.name None In [7]: print template2.name html_template
Метод filename - отображает имя шаблона в файловой системе, если он был загружен из нее. В остальных случаях, возвращается значение None:
In [8]: print template1.filename <template> In [9]: print template2.filename html_templates/html_template
Метод render([context]) - используется для обработки шаблона и подстановки значений в него. В качестве контекста может быть: словарь, именованные аргументы:
In [11]: template1.render(name='Nick') Out[11]: u'Hello Nick!' In [12]: template1.render({'name':'Nick'}) Out[12]: u'Hello Nick!'
Метод generate([context]) - используется для обработки очень больших шаблонов.
Этот метод не обрабатывает весь шаблон за один раз, а проходится по шаблону и шаг за шагом обрабатывает его и возвращает на выходе генератор.
В качестве контекста могут быть те же объекты, что и для метода render:
In [13]: template1 = jinja2.Template(""" ....: Hello {{name}}! ....: How are you, {{name}}? ....: {{question}} ....: """) In [14]: print template1.generate() <generator object generate at 0x10cb69fa0> In [15]: for i in template1.generate(name='Nick',question='What?'): ....: print i ....: Hello Nick! How are you, Nick? What?
Метод stream([context]) - работает так же, как и generate(), но возвращает объект TemplateStream.
[править] Синтаксис шаблонов
Шаблон Jinja это обычный текстовый файл, в котором, с помощью различных выражений, можно указать какие значения в шаблоне должны быть заменены.
Кроме выражений, в шаблоне могут быть, например, различные конструкции, которые управляют логикой обработки данных, при формировании документа по шаблону.
Jinja использует такие разделители (они могут быть изменены):
- {% ... %} - для структур, таких как for, if
- {{ ... }} - для выражений
- {# ... #} - комментарии
[править] Переменные
Переменные шаблона определяются в словаре, который передается шаблону.
Переменной может быть любой объект Python. В зависимости от того, какой именно объект передан, можно, например, обращаться к атрибутам переменной или к элементам.
Пример переменной:
<h2>Привет, {{current_user}}</h2>
Если у переменной есть какие-то атрибуты, можно к ним обращаться в шаблоне:
<h2>Привет, {{ current_user.timezone }}</h2>
[править] Фильтры
Переменные можно модифицировать с помощью фильтров.
Фильтры отделяются от переменных символом pipe |:
{{ users|sort }}
Список встроенных фильтров.
[править] Управляющие структуры
[править] Цикл for
Цикл for проходит по каждому элементу последовательности.
Простой пример цикла for в шаблоне, который генерирует список пользователей:
<h1>Members</h1> <ul> {% for user in users %} <li>{{ user}}</li> {% endfor %} </ul>
Пример цикла for, который проходится по списку словарей и заполняет поля таблицы:
<table class="table table-hover"> <tr> <th>Lab</th> <th>Student</th> <th>Статус</th> <th>Отчет</th> </tr> {% for lab in labs %} <tr> <td>{{lab['lab_id']}}</td> <td>{{lab['st_name']}}</td> <td>{{lab['status']}}</td> <td><a href="report/{{lab['lab_id']}}_{{lab['st_id']}}">Перейти к отчету</a></td> </tr> {% endfor %} </table>
[править] if
{% if not current_user.is_authenticated %} <h2>Привет, незнакомец</h2> {% else %} <h2>Привет, {{current_user}}</h2> {% endif %}
[править] Вопросы
[править] Как раскрыть шаблон Jinja2 и сгенерировать на его основе результирующий файл?
Пример (источник [1]):
from jinja2 import Environment, FileSystemLoader env = Environment(loader=FileSystemLoader('templates')) template = env.get_template('test.html') output_from_parsed_template = template.render(foo='Hello World!') with open("my_new_file.html", "wb") as fh: fh.write(output_from_parsed_template)
Здесь шаблон test.html читается из каталога templates/, раскрывается, и результат преобразования записывается в my_new_file.html в текущем каталоге.
[править] Дополнительная информация
- Jinja2 API (англ.) — руководство по языку шаблонов Jinja2