Формирование HTML во фреймворках — отдельная нетривиальная тема. Можно создавать HTML напрямую в виде строки, но такой способ перестает работать на реальных сайтах, где HTML одной страницы — это сотни или тысячи строк. Чтобы упростить работу с HTML, используют шаблонизаторы. В этом уроке мы познакомимся с ними подробнее.
HTML в виде строки — плохой подход
Представим, что мы создаем HTML-страницу в виде строки:
@app.route("/courses/<name>/")
def courses_show(name):
courses = get_courses(name)
return (
"""
<html>
<head>
<title>"""
+ courses.name
+ """</title>
</head>
<body>
<h1>"""
+ courses.name
+ """</h1>
<div>"""
+ courses.body
+ """</div>
</body>
</html>
"""
)
У такого подхода много недостатков:
- Он небезопасен и может привести к взлому
- С ростом количества HTML поддерживать такой код станет практически невозможно из-за неудобства анализа и редактирования
- В таком коде будут возникать постоянные проблемы — придется экранировать одинарные или двойные кавычки
- В таком коде легко допустить ошибку в HTML и сложно ее обнаружить
- В типичных сайтах большая часть HTML общая для разных страниц. Выделить ее с этим подходом очень сложно
Чтобы решать подобные проблемы, придумали шаблонизаторы.
Шаблонизаторы
Шаблонизаторы — специализированные библиотеки, которые позволяют описывать шаблон отдельно от остальной части кода. Мы будем использовать Jinja2, который по умолчанию установлен во Flask.
Чтобы использовать шаблонизатор Jinja2, его нужно подключить:
from flask import render_template
@app.route("/users/<id>")
def users_show(id):
return render_template(
"index.html",
name=id,
)
Функция render_template()
выполняет рендеринг указанного шаблона и добавляет результат в ответ. Сама функция принимает на вход два параметра:
- Путь до нужного шаблона
- Контекст — набор именованных аргументов, который будет доступен внутри шаблона. Сюда можно передавать все что угодно.
Далее добавляем файл templates/index.html со следующим содержимым:
<h1>Hello, {{ name }}</h1>
Теперь откройте браузер и попробуйте загрузить страницу http://localhost:8000/users/nick.
curl localhost:8000/users/nick
<h1>Hello, nick</h1>
Вместо кода {{ name }}
на экране появилось значение аргумента name
. Шаблонизатор берет весь контекст, который приводится после названия шаблона, и создает внутри шаблона локальные переменные. При этом имя локальной переменной и имя передаваемого именованного аргумента совпадают. Этот принцип работает всегда. Затем все переданные контекстом переменные подставляются в их плейсхолеры в шаблоне.
Если вам нужно вывести данные на странице, то добавляйте новые аргументы и обращайтесь к ним в шаблоне через переменные.
Шаблонизатор Jinja2 отличается от обычного HTML тем, что содержит в себе дополнительные конструкции:
{{ ... }}
— для вывода переменных{% ... %}
— для управления логикой шаблона{# ... #}
— для комментариев
Язык шаблонов Jinja отчасти похож на синтаксис языков программирования. В нем также можно использовать условия, циклы, преобразовывать данные.
<!-- конструкция for -->
{% for course in courses %}
{{ course }}
{% endfor %}
Ипользование шаблонов
Теперь, когда мы добавили поддержку шаблонов во фреймворк, появляется способ создавать нетривиальные сайты. Ниже пример обработчика и шаблона для вывода курсов.
Обработчик:
@app.route("/courses/")
def courses_index():
courses = get_courses() # Возвращает список курсов, которые представлены словарем
return render_template(
"courses/view.html",
# передаем в переменную courses
courses=courses,
)
Шаблон:
<!-- courses/view.html -->
<table>
<!-- в переменной courses будут подставлены данные из обработчика -->
{% for course in courses %}
<tr>
<td>
{{ course.id }}
</td>
<td>
{{ course.name }}
</td>
</tr>
{% endfor %}
</table>
При открытии страницы /courses/ у нас будет отображаться следующий список:
Блок {% for course in courses %} ... {% endfor %}
отвечает за цикл, который выводит HTML-код, расположенный внутри него. Так мы выводим список всех записей, который передали в шаблон из представления как переменную courses
.
Использовать HTML напрямую в виде строки можно, но это небезопасно, неудобно, проблематично и сложно. Поэтому стоит использовать шаблонизаторы. Они позволяют описывать шаблон отдельно от остальной части кода, что упрощает работу с HTML-страницами.
Самостоятельная работа
- Добавьте обработчик для просмотра страницы пользователя
- Создайте для него шаблон templates/users/show.html. Выведите в нем идентификатор пользователя и никнейм пользователя
- Выполните запрос к странице /users/5
- Попробуйте поменять число
Эталонное приложение
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.