Работа с 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-тэги (например, замену < и > на < и >), то можете сказать:
<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.