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]Stackoverflow.png):

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
Источник — «http://xgu.ru/wiki/Jinja2»