Что такое шаблонизатор Twig и зачем он нужен?
Автор: Дмитрий Ченгаев
2023-03-13
Назад Содержание Далее
Подробный курс по работе с Twig
Знакомимся с понятием шаблонизатора
Изучая фреймворк Symfony, рано или поздно, вы столкнетесь с таким понятием как шаблонизатор. Давайте будем разбираться с тем, что такое шаблонизатор и зачем он нужен.
В Symfony используется такой шаблонизатор, который называется Twig. На самом деле Twig — это не единственный шаблонизатор, который мы с вами можем использовать. Вы можете использовать любой другой шаблонизатор.
Но, по умолчанию, в Symfony используется именно шаблонизатор Twig.
Давайте будем разбираться, зачем нам нужен шаблонизатор и для каких целей он используется.
Если мы с вами вспомним модель MVC (модель — вид — контроллер), о которой мы с вами говорили несколько ранее, то шаблонизатор — это то, что относится к части «Вида».
Как вы помните, задача вида у нас представить данные, которые будут выданы по запросу пользователя. Точно также шаблонизатор. Его основная задача представить данные для отображения пользователю.
Чтобы вывести файл Twig, мы с вами должны создать контроллер и роут. Подробнее об этих понятиях мы также останавливались в предыдущих видео.
Что внутри файла Twig?
Файл шаблонизатора — это обычный текстовый файл. Для Twig этот файл имеет 2 расширения.
file.html.twig
Это означает то, что этот файл у нас содержит HTML-разметку и во вторых этот файл является служебным файлом шаблонизатора Twig.
По сути, в этом файле у нас содержаться 2 части: обычный html-код с простыми html-тэгами, встроенные стили CSS, встроенный Javascript-код и.т.д.
В отличии от обычной html-страницы, дополнительно к разметке документа там также выводятся определенные данные, которые могли быть переданы в него из контроллера. С помощью специальных конструкций, эти данные встраиваются в исходный twig-файл.
Данные на сервере могут меняться и автоматически они также меняются в twig файле. Т.е. мы получили html-страницу, которая содержит какие-то данные с веб-сервера.
Кроме данных в twig файле могут находиться какие-то служебные функции, которые упрощают представление этих данных.
Т.е. шаблонизатор — это что-то вроде некого шаблона и в этот шаблон мы можем передавать некие переменные, которые зависят от состояния нашего сервера.
Поэтому, шаблонизатор и происходит от слова «шаблон». Там содержится какая-то шаблонная страница, шаблонный html-код и в него вставляются переменные данные.
Т.е. шаблонизатор — это что-то вроде службы, которая подготавливает html-страницу со всеми необходимыми данными, которые отражают состояние нашего веб-сервера и возвращают эти данные контроллеру.
А контроллер уже возвращает готовый html-код тому посетителю сайта. который его запросил.
Таким образом это работает. Надеюсь, что стало понятнее что такое шаблонизатор и для чего он нужен и теперь можно приступить к рассмотрению конкретных примеров по работе с этим инструментом.
1) Попробуйте найти в Сети информацию о том, какие еще есть шаблонизаторы, кроме Twig. Напишите их название в комментарии под этим видео.
2) Создайте отдельный раздел в своей базе знаний программиста (решение, которое использую я), который будет называться Twig. Вам еще не раз придется к нему обращаться на практике.
Назад Содержание Далее
- Комментарии
- Отзывы
что это такое, какие бывают
Что такое шаблонизатор в SEOШаблонизаторы (механизмы создания шаблонов JavaScript) позволяют добавлять динамическую логику к статическим HTML-страницам. Например, вы можете объявить переменную, которую механизм заменяет фактическим значением при выполнении. Таким же образом можно использовать условные выражения, циклы, фильтры, миксины, другие конструкции.
Шаблонные движки JavaScript ускоряют интерфейсную разработку, упрощают и ускоряют отладку, обслуживание. Каждый движок имеет собственный синтаксис, который необходимо изучить. Однако кривая обучения обычно довольно плоская, поскольку синтаксисы шаблонов целенаправленно просты, легко запоминаются.
Особенность шаблонизаторов — они позволяют нам создавать повторно используемые компоненты, называемые частичными, которые можно повторно использовать в других файлах. Это предотвращает дублирование кода и упрощает внесение изменений.
Сегодня доступно несколько шаблонизаторов. Популярные из них — Pug (fka Jade), Handlebars, EJS, Mustache, Swig и другие.
Nunjucks
Nunjucks — это высокопроизводительный полнофункциональный шаблонизатор JavaScript, вдохновленный механизмом Jinja2 для Python. Он разработан и поддерживается Mozilla, которая также использует Nunjucks для своих собственных продуктов (Firefox Marketplace и Mozilla Webmaker). Nunjucks имеет множество расширенных функций: встроенные фильтры, аргументы ключевых слов, наследование, асинхронные шаблоны и др.
Вы можете добавить Nunjucks в свой проект либо с помощью npm, либо путем добавления библиотеки nunjucks.js на HTML-страницу. Nunjucks поддерживает все современные браузеры, однако необходимо использовать ES5-shim для поддержки Internet Explorer 11.
PugPug ранее был известен как Jade. Команде разработчиков пришлось переименовать его, когда выяснилось, что Jade — зарегистрированная торговая марка. Pug позволяет быстро писать статические шаблоны. Синтаксис Pug включает в себя условные выражения, фильтры, включения, итерации, миксины, интерполяцию и другие логические конструкции.
Он полностью интегрируется с Express.js в качестве поддерживаемого механизма просмотра. Если вы хотите использовать свои шаблоны Pug при разработке React, можно перенести их в JSX, используя плагин Babel. Вы можете разрабатывать темы WordPress, используя шаблоны Pug с помощью плагина Wordless. Он добавляет Pug, Sass, CoffeeScript и Webpack в вашу тему WordPress.
Mustache.js
Mustache.js — это JavaScript-реализация популярной системы шаблонов {{mustache}}. Помимо JavaScript, {{mustache}} также доступен в Ruby, PHP, C # /. NET, Android, C ++ и многих других языках программирования. Это хороший выбор для разработчиков, которые кодируют на нескольких языках, так как синтаксис нужно осваивать только один раз.
Шаблоны, созданные с помощью {{mustache}}, не имеют логики, поскольку синтаксис не имеет операторов if-else, циклов for и аналогичной логики — только теги шаблонов. Чтобы использовать Mustache.js, нужно определить объект представления для данных и шаблон. Mustache.js используется многими известными компаниями: Linkedin, Twitter, PayPal, Buzzfeed.
HandlebarsHandlebars позволяет строить смысловые шаблоны, похожие на шаблоны усов. В большинстве случаев можно использовать шаблоны Mustache и Handlebars взаимозаменяемо, однако есть и некоторые исключения. Синтаксис Handlebars — это надмножество Mustache — он расширяет синтаксис Mustache дополнительными функциями, которые упрощают создание шаблонов.
С Handlebars можно использовать вложенные пути, в то время как Mustache поддерживает только простые пути. Функция Block Expression позволяет создавать помощников, которые вызывают шаблон в разных контекстах. Можно передавать помощникам в качестве аргументов литеральные значения, включая строки, числа, логические значения, null и undefined. Согласно тестам производительности, текущая версия Handlebars (Handlebars 4) в 5&ndash7 раз быстрее, чем его эквивалент Mustache.
Template7
Template7 — это механизм создания шаблонов JavaScript, который следует подходу, ориентированному на мобильные устройства. Он создан и поддерживается командой, стоящей за популярным мобильным фреймворком Framework7, который позволяет создавать приложения для iOS и Android. Template7 также используется в качестве механизма шаблонов по умолчанию в Framework7. Он имеет синтаксис, аналогичный Handlebars, но примерно в 2&ndash4 раза быстрее. Template7 также довольно легкий — уменьшенная и сжатая с помощью gzip версия весит всего 1 КБ.
С Template7 вы можете встраивать выражения Handlebars в обычные файлы HTML. Он также имеет встроенные помощники, которые упрощают динамическую обработку контента. Например, вы можете использовать {{#each}}&hellip {{else}} .. {{/ each}}, {{#if}}&hellip {{else}}&hellip {{/ if}}, {{# if}}&hellip {{else}}&hellip {{/ except}} и другие выражения блока в качестве вспомогательных функций. Template7 позволяет определять настраиваемые помощники и повторно использовать шаблоны через частичные файлы.
JsRender
JsRender — это расширяемый механизм шаблонов JavaScript, который можно использовать по-разному. Он позволяет отображать шаблоны как на сервере (Node.js), так и в браузере. Загрузить его можно с помощью jQuery или без него. Версия Node.js также предоставляет встроенную интеграцию с Express, Hapi и Browserify.
JsRender использует синтаксис, похожий на усы, нужно вставить теги шаблона в пару двойных фигурных скобок {{&hellip}}. Синтаксис включает вычисления, частичные, условные выражения, циклы, итерации и другие логические конструкции.
Можно создавать собственные теги и расширять теги шаблонов по умолчанию, например, тег {{for}}. Синтаксис JsRender содержит помощники, преобразователи (например, преобразователь в верхний регистр), а также богатые выражения для облегчения создания сложной логики.
doT.js
Механизм создания шаблонов JavaScript doT.js делает упор на скорость, производительность. Использовать его можно с npm, либо добавив библиотеку JS на свою HTML-страницу. doT.js не имеет зависимостей, нагрузок даже при больших шаблонах — все выполняется довольно быстро. Вы можете выбирать между оценкой времени выполнения и оценкой времени компиляции. Если данные не меняются при каждом запуске, выбрайте последний.
Синтаксис doT по умолчанию ссылается на данные с именем переменной it. Однако вы можете изменить его, отредактировав файл настроек компиляции. Синтаксис позволяет использовать частичные выражения, условные выражения, массивы, интерполяцию, циклы и другую логику. Многие разработчики также используют doT вместе с Express. js.
Шаблонные движки JavaScript могут сэкономить вам много времени. В качестве альтернативы используйте литералы шаблонов ES6. Большинство из них имеют гораздо больше опций, возможностей.
Ускорить разработку помогут интерфейсные фреймворки, которые предоставляют заранее определенную структуру и решают несколько общих задач.
Использование механизмов шаблонов с Express
Механизм шаблонов позволяет вам использовать статические файлы шаблонов в вашем приложении. Во время выполнения механизм шаблонов заменяет переменные в файле шаблона с фактическими значениями и преобразует шаблон в файл HTML, отправляемый клиенту. Такой подход упрощает разработку HTML-страницы.
Некоторые популярные шаблонизаторы, работающие с Express, — это Pug, Усы и EJS. Генератор приложений Express использует Jade по умолчанию, но также поддерживает несколько других.
См. Механизмы шаблонов (Express wiki) для списка механизмов шаблонов, которые вы можете использовать с Express. См. также Сравнение движков шаблонов JavaScript: Jade, Mustache, Dust и другие.
Для рендеринга файлов шаблонов установите следующие свойства настройки приложения, установленные в app.js
в приложении по умолчанию, созданном генератором:
-
views
, каталог, в котором находятся файлы шаблонов. Например:app.set('просмотры', './просмотры')
. По умолчанию это каталогviews
в корневом каталоге приложения. -
механизм просмотра
, механизм шаблонов для использования. Например, чтобы использовать механизм шаблонов Pug:
.
Затем установите соответствующий пакет npm обработчика шаблонов; например установить мопс:
$ npm установить мопс --save
Механизмы шаблонов, совместимые с Express, такие как Jade и Pug, экспортируют функцию с именем __express(filePath, options, callback)
,
который вызывается функцией res. render()
для рендеринга кода шаблона.
Некоторые механизмы шаблонов не следуют этому соглашению. Consolidate.js Библиотека следует этому соглашению, сопоставляя все популярные механизмы шаблонов Node.js, и поэтому без проблем работает в Express.
После того, как механизм просмотра установлен, вам не нужно указывать механизм или загружать модуль механизма шаблонов в вашем приложении; Express загружает модуль внутрь, как показано ниже (для приведенного выше примера).
app.set('движок просмотра', 'мопс')
Создайте файл шаблона Pug с именем index.pug
в каталоге views
со следующим содержимым:
html голова название = название тело h2= сообщение
Затем создайте маршрут для рендеринга index.pug 9файл 0016. Если свойство
механизма просмотра
view
. В противном случае вы можете его опустить.
app.get('/', (req, res) => { res. render('index', { title: 'Привет', message: 'Привет!' }) })
Когда вы делаете запрос на домашнюю страницу, файл index.pug
будет отображаться как HTML.
Примечание. Кэш механизма просмотра не кэширует содержимое вывода шаблона, а только сам базовый шаблон. Представление по-прежнему перерисовывается с каждым запросом, даже если кеш включен.
Чтобы узнать больше о том, как механизмы шаблонов работают в Express, см.: «Разработка шаблонизаторов для Express».
Как работает механизм шаблонов — Письма Шипэн Фэна
написано Шипэн Фэн на 2016-08-01
Я давно пользуюсь шаблонизаторами и наконец нашел время найти как работает шаблонизатор.
Введение
Вкратце, механизм шаблонов — это инструмент, который можно использовать для выполнения задач программирования. с большим количеством текстовых данных. Наиболее распространенное использование — генерация HTML в веб-приложениях. В частности, в Python у нас есть несколько вариантов прямо сейчас.
Прежде чем мы перейдем к деталям реализации, давайте сначала рассмотрим простое использование API:
из шаблона импорта торнадо СТРАНИЦА_HTML = """ Привет, {{ имя пользователя }}! <ул> {% для работы в job_list %}
Здесь имя пользователя будет динамическим в html странице, так же как и список вакансий. Ты
можно установить
и запустите код, чтобы увидеть результат.
Реализация
Если мы внимательно посмотрим на PAGE_HTML
, мы легко обнаружим, что строка шаблона
состоит из двух частей: статической текстовой части и динамической части. Мы используем спец.
обозначение для выделения динамической части. В целом, шаблонизатор должен
возьмите строку шаблона и выведите статическую часть как есть, для этого также необходимо
обрабатывать динамические части с заданным контекстом и давать правильный строковый результат.
Таким образом, в основном механизм шаблонов — это всего лишь одна функция Python:
def template_engine(template_string, **контекст): # процесс здесь вернуть результат_строка
Во время процедуры обработки шаблонизатор имеет две фазы:
- парсинг
- визуализация
Этап синтаксического анализа берет строку шаблона и создает что-то, что может быть предоставлено. Рассматривайте строку шаблона как исходный код, инструмент синтаксического анализа может быть либо интерпретатор языка программирования, либо компилятор языка программирования. Если инструмент является интерпретатором, синтаксический анализ создает структуру данных, инструмент рендеринга пройдется по структуре и выдаст результирующий текст.
Компиляция
Как было сказано выше, теперь нам нужно проанализировать строку шаблона и инструмент анализа в Модуль шаблонов торнадо компилирует шаблоны в код Python. Наш инструмент для разбора просто одна функция Python, которая выполняет генерацию кода Python:
def parse_template(template_string): # компиляция вернуть python_source_code
Прежде чем мы перейдем к реализации parse_template
, давайте посмотрим код
производит, вот пример исходной строки шаблона:
Привет, {{ имя пользователя }}! <ул> {% для работы в работах %}
Наша функция parse_template
скомпилирует этот шаблон в код Python, который
только одна функция, упрощенная версия:
def _execute(): _буфер = [] _buffer. append('\n\n Привет, ') _tmp = имя пользователя _buffer.append (ул (_tmp)) _buffer.append('!\n
- \n ')
на работу в вакансии:
_buffer.append('\n
- ') _tmp = задание.имя # упрощено, здесь нужно сделать несколько проверок _tmp _buffer.append (ул (_tmp)) _buffer.append(' \n') _buffer.append('\n
Теперь наш шаблон анализируется в функцию с именем _execute
, доступ к этой функции
все переменные контекста из глобального пространства имен. Эта функция создает список строк
и соедините их вместе как результирующую строку. Имя пользователя
помещается в локальное имя _tmp
, поиск локального имени выполняется намного быстрее, чем поиск глобального. Есть
другие оптимизации, которые можно выполнить здесь, например:
_buffer.append('hello') _append_buffer = _buffer.append # быстрее для многократного использования _append_buffer('привет')
Выражения в {{ . .. }}
оцениваются и добавляются к списку строкового буфера.
В модуле шаблона торнадо нет ограничений на выражения, которые вы можете
включите в свои заявления, если и для блоков будут переведены точно в Python.
Код
Теперь посмотрим на реальную реализацию. Основным интерфейсом, который мы используем, является
Класс Template
, когда мы создаем один объект Template
, мы компилируем строку шаблона
и позже мы можем использовать его для визуализации данного контекста. Нам нужно скомпилировать только один раз и
вы можете кэшировать объект шаблона где угодно, упрощенная версия конструктора:
Шаблон класса (объект): def __init__(я, template_string): self.code = parse_template (template_string) self.compiled = compile(self.code, '', 'exec')
Компиляция
скомпилирует исходный код в объект кода. Мы можем выполнить это
позже с оператором exec
. Теперь давайте создадим функцию parse_template
,
во-первых, нам нужно разобрать нашу строку шаблона в список узлов, которые знают
как сгенерировать код Python, нам нужна функция с именем _parse
, мы увидим
функция позже, сейчас нам нужны помощники, чтобы помочь с чтением шаблона
файл, у нас есть класс _TemplateReader
, который обрабатывает чтение для нас, когда мы
использовать файл шаблона. Нам нужно начать с самого начала и идти вперед
чтобы найти некоторые специальные обозначения, _TemplateReader
сохранит текущую позицию
и дайте нам способы сделать это:
class _TemplateReader(object): def __init__(я, текст): селф.текст = текст селф.поз = 0 def найти (я, игла, начало = 0, конец = нет): позиция = self.pos старт += поз. если конец равен None: index = self.text.find (игла, начало) еще: конец += поз. index = self.text.find (игла, начало, конец) если индекс != -1: индекс -= позиция возвращаемый индекс защита потребления (я, количество = нет): если количество равно None: count = len(self.text) - self.pos newpos = self.pos + количество s = self.text[self.pos:newpos] self.pos = новая позиция вернуть с оставшаяся защита (я): вернуть len(self.text) - self.pos защита __len__(я): вернуть self. remaining() def __getitem__(я, ключ): если ключ <0: вернуть self.text[ключ] еще: вернуть self.text[self.pos + ключ] защита __str__(я): вернуть self.text[self.pos:]
Чтобы помочь с созданием кода Python, нам нужен класс _CodeWriter
, этот класс
пишет строки кода и управляет отступами, также это один контекстный менеджер Python:
class _CodeWriter(object): защита __init__(сам): self.buffer = cStringIO.StringIO() self._indent = 0 деф отступ(сам): вернуть себя определение indent_size (я): вернуть self._indent защита __enter__(сам): self._indent += 1 вернуть себя def __exit__(я, *аргументы): self._indent -= 1 def write_line (я, строка, отступ = нет): если отступ == Нет: отступ = self._indent для я в xrange (отступ): self.buffer.write(" ") print >> self.buffer, строка защита __str__(я): вернуть self. buffer.getvalue()
В начале parse_template
мы сначала создаем одну программу чтения шаблонов:
def parse_template(template_string): читатель = _TemplateReader (template_string) file_node = _File (_parse (читатель)) писатель = _CodeWriter() file_node.generate(писатель) вернуть ул (писатель)
Затем мы передаем считыватель функции _parse
и получаем список узлов.
Все эти узлы являются дочерними узлами узла файла шаблона. Мы создаем
один объект CodeWriter, файловый узел записывает код Python в CodeWriter,
и мы возвращаем сгенерированный код Python. _Node
класс будет обрабатывать Python
генерация кода для конкретного случая, мы увидим это позже. Теперь вернемся к нашему _parse
функция:
def _parse(reader, in_block=None): тело = _ChunkList([]) пока верно: # Найти следующую директиву шаблона кудрявый = 0 пока верно: кудрявый = reader. find("{", кудрявый) если curly == -1 или curly + 1 == reader.remaining(): # конец файла если в_блоке: поднять ParseError("Отсутствует блок {%% end %%} для %s" % in_block) body.chunks.append(_Text(reader.consume())) вернуть тело # Если первая фигурная скобка не является началом специального токена, # начать поиск с символа после него если читатель [кудрявый + 1] не в ("{", "%"): кудрявый += 1 продолжать # Если подряд более 2 завитушек, используйте # самые внутренние. Это полезно при создании языков # как латекс, где завитки также имеют смысл если (curly + 2 < reader.remaining() и читатель [кудрявый + 1] == '{' и читатель [кудрявый + 2] == '{'): кудрявый += 1 продолжать перерыв
Мы зацикливаемся, чтобы найти директиву шаблона в оставшемся файле, если мы достигнем конец файла, мы добавляем текстовый узел и выходим, иначе мы нашли одна директива шаблона.
# Добавить любой текст перед специальным токеном если фигурные > 0: body.chunks.append(_Text(reader.consume(curly)))
Перед обработкой специального токена мы добавляем текстовый узел, если есть статическая часть.
start_brace = reader.consume(2)
Получить нашу стартовую фигурную скобку, если она должна быть '{{'
или '{%'
.
# Выражение если start_brace == "{{": конец = читатель.найти("}}") если end == -1 или reader.find("\n", 0, end) != -1: поднять ParseError("Отсутствует конечное выражение }}") содержимое = читатель.consume(конец).strip() читатель.consume(2) если не содержание: поднять ParseError("Пустое выражение") body.chunks.append(_Expression(содержимое)) продолжать
Начальная фигурная скобка '{{'
, и здесь у нас есть выражение, просто получите содержимое
выражения и добавить один узел _Expression
.
# Блок утверждать start_brace == "{%", start_brace конец = читатель.найти("%}") если end == -1 или reader.find("\n", 0, end) != -1: поднять ParseError("Отсутствует конечный блок %}") содержимое = читатель.consume(конец).strip() читатель.consume(2) если не содержание: поднять ParseError("Пустой тег блока ({% %})") оператор, пробел, суффикс = содержимое.раздел(" ") # Конечный тег если оператор == "конец": если не в_блоке: поднять ParseError("Дополнительный блок {% end %}") вернуть тело оператор elif в ("попробуй", "если", "для", "пока"): # рекурсивно анализируем внутреннее тело block_body = _parse (читатель, оператор) блок = _ControlBlock (содержимое, блок_тело) body.chunks.append(блок) продолжать еще: поднять ParseError("неизвестный оператор: %r" % оператор)
Здесь у нас есть блок, обычно мы получаем тело блока рекурсивно и добавляем
узел _ControlBlock
, тело блока должно быть списком узлов. Если мы столкнемся
an {% end %}
, блок заканчивается, и мы выходим из функции.
Пришло время узнать секреты класса _Node
, это довольно просто:
class _Node(object): def сгенерировать (я, писатель): поднять NotImplementedError()
класс _ChunkList(_Node): def __init__(я, куски): self.chunks = куски def сгенерировать (я, писатель): для чанка в self.chunks: chunk.generate(писатель)
A _ChunkList
— это просто список узлов.
класс _File(_Node): def __init__(я, тело): самотело = тело def сгенерировать (я, писатель): Writer.write_line("def _execute():") с автором.indent(): писатель.write_line("_buffer = []") self.body.generate (писатель) Writer.write_line("возврат ''.join(_buffer)")
Узел _File
записывает функцию _execute
в CodeWriter.
класс _Expression(_Node): def __init__(я, выражение): self. expression = выражение def сгенерировать (я, писатель): Writer.write_line("_tmp = %s" % self.expression) писатель.write_line("_buffer.append(str(_tmp))") класс _Text(_Node): def __init__(я, значение): самостоятельная ценность = ценность def сгенерировать (я, писатель): значение = собственное значение если значение: Writer.write_line('_buffer.append(%r)'% значение)
_Текст 9Узел 0016 и
_Expression
также очень прост, просто добавьте то, что вы
получить из источника шаблона.
класс _ControlBlock(_Node): def __init__(я, оператор, тело = нет): self.statement = заявление самотело = тело def сгенерировать (я, писатель): Writer.write_line("%s:" % self.statement) с автором.indent(): self.body.generate (писатель)
Для узла _ControlBlock
нам нужно сделать отступ и написать список дочерних узлов с помощью
отступ.
Теперь вернемся к части рендеринга, мы рендерим контекст, используя generate
метод объекта Template
, генерирует функцию
, просто вызывая скомпилированный Python
код:
def generate(self, **kwargs): пространство имен = {} namespace.