SimpleTemplate Engine
Bottle поставляется со встроенным, быстрым, мощным и простым в освоении шаблонизатором под названием SimpleTemplate или stpl вкратце. Это движок по умолчанию, используемый помощниками view() и template(), но также может быть использован как самостоятельный шаблонизатор общего назначения. Этот документ объясняет синтаксис шаблонов и показывает примеры для распространённых случаев использования.
Базовое использование API:
SimpleTemplate реализует API BaseTemplate:
>>> from bottle import SimpleTemplate
>>> tpl = SimpleTemplate('Hello {{name}}!')
>>> tpl.render(name='World')
u'Hello World!'
В этом документе мы используем помощника template() в примерах для простоты:
>>> from bottle import template
>>> template('Hello {{name}}!', name='World')
u'Hello World!'
Просто имейте в виду, что компиляция и рендеринг шаблонов — это две разные операции, даже если помощник template() скрывает этот факт. Шаблоны обычно компилируются только один раз и кешируются внутри, но рендерятся многократно с различными аргументами ключевых слов.
Синтаксис SimpleTemplate
Python — очень мощный язык, но его чувствительный к отступам синтаксис затрудняет его использование в качестве языка шаблонов. SimpleTemplate устраняет некоторые из этих ограничений и позволяет вам писать чистые, удобочитаемые и поддерживаемые шаблоны, сохраняя при этом полный доступ к функциям, библиотекам и скорости языка Python.
Предупреждение
Синтаксис SimpleTemplate компилируется непосредственно в байткод Python и выполняется при каждом вызове SimpleTemplate.render(). Не рендерите недоверенные шаблоны! Они могут содержать и выполнять вредный код Python.
Встроенные операторы
Вы уже узнали об использовании оператора {{...}} из примера “Hello World!” выше, но есть и больше: любой оператор Python разрешён в фигурных скобках, если он возвращает строку или что-то, что имеет строковое представление:
>>> template('Hello {{name}}!', name='World')
u'Hello World!'
>>> template('Hello {{name.title() if name else "stranger"}}!', name=None)
u'Hello stranger!'
>>> template('Hello {{name.title() if name else "stranger"}}!', name='mArC')
u'Hello Marc!'
Встроенный оператор Python выполняется во время рендеринга и имеет доступ ко всем аргументам ключевых слов, переданным методу SimpleTemplate.render(). HTML-специальные символы автоматически экранируются для предотвращения атак XSS. Вы можете начать оператор с восклицательного знака, чтобы отключить экранирование для этого оператора:
>>> template('Hello {{name}}!', name='<b>World</b>')
u'Hello <b>World</b>!'
>>> template('Hello {{!name}}!', name='<b>World</b>')
u'Hello <b>World</b>!'
Встроенный код Python
Символ % отмечает строку кода Python. Единственное отличие от реального кода Python заключается в том, что вам необходимо явно закрывать блоки оператором %end. Взамен вы можете выровнять код с окружающим шаблоном и не беспокоиться о правильном отступе блоков. Парсер SimpleTemplate обрабатывает это за вас. Строки, не начинающиеся с %, рендерятся как текст, как обычно:
%if name:
Hi <b>{{name}}</b>
%else:
<i>Hello stranger</i>
%end
Символ % распознается только в том случае, если это первый символ, не являющийся пробелом, в строке. Чтобы экранировать ведущий %, вы можете добавить второй. %% заменяется одним % в результирующем шаблоне:
This line contains a % but no python code. %% This text-line starts with '%' %%% This text-line starts with '%%'
Устранение символов перевода строки
Вы можете устранить символ перевода строки перед строкой кода, добавив двойной обратный слэш в конце строки:
<span>\\ %if True: nobreak\\ %end </span>
Этот шаблон генерирует следующий вывод:
<span>nobreak</span>
Оператор %include
Вы можете включать другие шаблоны, используя оператор %include sub_template [kwargs]. Параметр sub_template указывает имя или путь к включаемому шаблону. Остальная часть строки интерпретируется как список пар key=statement параметров, аналогичных аргументам ключевых слов в вызовах функций. Они передаются в подшаблон аналогично вызову SimpleTemplate.render(). Допускается и синтаксис **kwargs для передачи словаря:
%include header_template title='Hello World' <p>Hello World</p> %include footer_template
Оператор %rebase
Оператор %rebase base_template [kwargs] вызывает рендеринг base_template вместо исходного шаблона. Базовый шаблон затем включает исходный шаблон с пустым оператором %include и имеет доступ ко всем переменным, указанным в kwargs. Таким образом, возможно обернуть шаблон другим шаблоном или смоделировать функцию наследования, присутствующую в некоторых других шаблонизаторах.
Предположим, у вас есть шаблон содержимого и вы хотите обернуть его в общую рамочную HTML-структуру. Вместо того, чтобы включать несколько шаблонов заголовка и подвала, вы можете использовать один базовый шаблон для рендеринга фрейма макета.
Базовый шаблон с именем layout.tpl:
<html>
<head>
<title>{{title or 'No title'}}</title>
</head>
<body>
%include
</body>
</html>
Основной шаблон с именем content.tpl:
This is the page content: {{content}}
%rebase layout title='Content Title'
Теперь вы можете отобразить content.tpl:
>>> print template('content', content='Hello World!')
<html> <head> <title>Content Title</title> </head> <body> This is the page content: Hello World! </body> </html>
Более сложный сценарий включает цепочку переопределений и несколько блоков содержимого. Шаблон block_content.tpl определяет две функции и передаёт их базовому шаблону columns.tpl:
%def leftblock(): Left block content. %end %def rightblock(): Right block content. %end %rebase columns leftblock=leftblock, rightblock=rightblock, title=title
Базовый шаблон columns.tpl использует две вызываемые функции для рендеринга содержимого левой и правой колонки. Затем он оборачивает себя шаблоном layout.tpl , определённым ранее:
%rebase layout title=title <div style="width: 50%; float:left"> %leftblock() </div> <div style="width: 50%; float:right"> %rightblock() </div>
Посмотрим, как block_content.tpl рендерит:
>>> print template('block_content', title='Hello World!')
<html> <head> <title>Hello World</title> </head> <body> <div style="width: 50%; float:left"> Left block content. </div> <div style="width: 50%; float:right"> Right block content. </div> </body> </html>
Функции пространства имён
Обращение к неопределённым переменным в шаблоне вызывает NameError и останавливает рендеринг немедленно. Это стандартное поведение Python и ничего нового, но обычный Python не имеет простого способа проверить доступность переменной. Это быстро становится раздражающим, если вы хотите поддерживать гибкие входные данные или использовать один и тот же шаблон в разных ситуациях. SimpleTemplate помогает здесь: следующие три функции определены в стандартном пространстве имён и доступны из любой точки шаблона:
-
defined(name) -
Возвращает True, если переменная определена в текущем пространстве имён шаблона, в противном случае — False.
-
get(name, default=None) -
Возвращает переменную или значение по умолчанию.
-
setdefault(name, default) -
Если переменная не определена, создаёт её со значением по умолчанию. Возвращает переменную.
Вот пример, который использует все три функции для реализации необязательных переменных шаблона различными способами:
% setdefault('text', 'No Text')
<h1>{{get('title', 'No Title')}}</h1>
<p> {{ text }} </p>
% if defined('author'):
<p>By {{ author }}</p>
% end
API SimpleTemplate
-
class SimpleTemplate(source=None, name=None, lookup=[], encoding='utf8', **settings)[source] -
-
classmethod split_comment(code)[source] -
Удаляет комментарии (#...) из кода Python.
-
render(*args, **kwargs)[source] -
Отрендерить шаблон, используя аргументы ключевых слов как локальные переменные.
-
Известные ошибки
Некоторые синтаксические конструкции, разрешенные в Python, проблематичны в шаблоне. Следующие синтаксические конструкции не будут работать с SimpleTemplate:
- Многострочные операторы должны заканчиваться обратной косой чертой (
\) и комментарий, если присутствует, не должен содержать дополнительных символов#. - Многострочные строки пока не поддерживаются.
© 2009–2017 Marcel Hellkamp
Licensed under the MIT License.
https://bottlepy.org/docs/0.11/stpl.html