← На главную

Работа с HTML-шаблонами в Python при помощи Jinja

Напомню, что у меня нет особого опыта веб-разработки на Python. Но поскольку рабочая теория на данный момент заключается в том, что это самый правильный скриптовый язык, мне бывает очень интересно сесть и поиграться с каким-нибудь Flask. Или, вот как в этот раз – с Jinja. В результате я написал небольшую шпаргалку по основам использования Jinja, чисто для себя. Уверен, вы уже давно владеете этим шаблонизатором в совершенстве, так что вам будет совершенно не интересно :)

Итак, коль скоро речь зашла о HTML, CSS и вот этом всем, не лишним будет упомянуть, как во Flask делается раздача статики:

@app.route('/static/<path:path>', methods=['GET']) def get_static(path): return send_from_directory('static', path)

Рендеринг же простейшего шаблона выглядит следующим образом:

@app.errorhandler(404) def error_404(e): data = flask.render_template('error.html', message = 'Not found!') return (data, 404)

… где содержимое templates/error.html:

<!-- Пропущено: html, head, body - все как обычно --> <h1>Что-то пошло не так!</h1> <p>{{ message }}</p> <!-- Пропущено -->

Поскольку у сайтов обычно есть повторяющиеся хидеры и футеры, традиционно шаблон выглядит как-то так:

{% extends "layout.html" %} {% block title %}Ошибка!{% endblock %} {% block body %} <h1>Что-то пошло не так!</h1> <p>{{ message }}</p> {% endblock %}

… где layout.html описывает шаблон страницы, в стиле:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>{% block title %}{% endblock %}</title> </head> <body> {% block body %}{% endblock %} </body> </html>

Иногда возникает необходимость использовать в шаблонах условные операторы:

{# еще ключевые слова: elif, else кстати, да, это - комментарий #} <li{% if section == "themes" %} class="active"{% endif %}> <a href="themes">Home</a> </li> <li{% if section == "submit" %} class="active"{% endif %}> <a href="submit">Submit</a> </li>

Более сложный пример, с определением макроса и циклом for:

{% macro render_themes(themes_list) %} {% if themes_list == [] %} <p><em>(None)</em></p> {% else %} {% for theme in themes_list %} <div class="theme"> <p>{{ theme["description"] }}</p> </div> {% endfor %} {% endif %} {% endmacro %}

Макрос вызывается очень просто:

{{ render_themes(current) }}

Если вы уверены, что выводимые данные правильно экранированы и все такое, и хотите отключить замену спецсимволов на HTML-тэги (например, замену < и > на &lt; и &gt;), то можете сказать:

<p>{{ encode_desc(description)|safe }}</p>

Чтобы Jinja могла вызвать процедуру, написанную на Python, используйте код в стиле:

def encode_desc(desc): # тут ваш код app.jinja_env.globals.update(encode_desc = encode_desc)

Как видите, все просто и понятно. Насколько я могу судить, приведенных в этом посте знаний должно хватить на все случаи жизни. Полную версию кода к посту вы найдете в этом репозитории на GitHub. Больше информации по Jinja – на официальном сайте.

Обратите также внимание на утилиту jinja2-cli, которую можно использовать, например, для генерации кода на каком-нибудь C. Еще из подобных проектов стоит обратить внимание на Cog.