Flask. Шаблоны.

Общее

Простые текстовые ответы подходят для реализации API, для взаимодействия программы с программой.

Для того что бы приложение было более дружелюбно к пользователю стоит возвращать ответ используя язык разметки HTML.

Самый простой способ - вернуть из обработчика строку, в которой будет содержаться требуемая разметка и информация:

@app.route('/html/', methods=['GET'])
def html():
    html_response = '<html><body>Был получен <p>{}</p> запрос.</body></html>'
    return html_response.format(request.method)

Но что если требуется выводить список сохраненных записей, количество которых заранее неизвестно? Реализуем такой обработчик:

data = (
    dict(name='Python', released='20.01.1991'),
    dict(name='Java', released='23.06.1995'),
    dict(name='GO', released='10.11.2009'),
)

@app.route('/table/', methods=['GET'])
def table():
    start = '<html><body><table border=1>'
    caption = '<caption>Языки программирования</caption>'
    header = '<tr><th>Название</th><th>Первый релиз</th></tr>'
    end = '</table></body></html>'
    tr_list = list()
    for item in data:
        tr_list.append(
            f'<tr><td>{item["name"]}</td><td>{item["released"]}</td></tr>'
        )
    content = ''.join(tr_list)
    html_response = ''.join((start, caption, header, content, end))
    return html_response.format(request.method)

В этом случае заметно усложняется реализация самого обработчика, а так же усложняется и отладка HTML разметки. Не проще ли хранить разметку отдельно от кода?

Шаблоны

Для решения описанной выше проблемы используются так называемые “Шаблоны”. По большому счету, шаблоны - обычные html-файлы с добавлением специальных синтаксических конструкций для установки изменяемых(динамических) данных.

Доработаем пример с таблицей с применением шаблонов. Для этого в директории с файлом Flask-приложения создайте новую директорию с названием “templates” (по умолчанию, Flask ищет в ней файлы шаблонов). Внутри новой директории создайте файл “table.html” со следующим содержимым:

<html>
    <body>
        <table border="1">
            <caption>Языки программирования</caption>
            <tr>
                <th>Название</th>
                <th>Первый релиз</th>
            </tr>
            {% for item in items %}
                <tr><td>{{ item.name }}</td><td>{{ item.released }}</td></tr>
            {% endfor %}
        </table>
    </body>
</html>

Как можно было заметить, помимо знакомых html-тэгов в файле добавились выражения вида:

  • {% for item in items %} - выражение обозначает начало блока цикла.

  • {{ item.name }} - выражение указывает что требуется вывести значение.

  • {% endfor %} - окончание блока цикла.

Если разделить на группы такие выражения, то получится:

  • Выражение вида {% ... %} - обозначает начало или окончание блока(for, if и т.д.).

  • Выражение вида {{ item }} - обозначает вывод значения.

Теперь реализуем обработчик, который будет использовать описанный выше шаблон:

from flask import render_template

data = (
    dict(name='Python', released='20.01.1991'),
    dict(name='Java', released='23.06.1995'),
    dict(name='GO', released='10.11.2009'),
)

@app.route('/template/', methods=['GET'])
def template():
    return render_template('table.html', items=data)

Для формирования ответа с использованием шаблона мы применили функцию render_template('table.html', items=data), где в качетве первого аргумента передали имя файла с шаблоном, а в качестве именованного второго - кортеж данных для вывода.

Important

Обратите внимание, что именованный аргумент(items из примера) должен иметь то же имя, что и переменная в шаблоне {% for item in items %}

Задания

Доработайте пользовательский и реализуйте API интерфейс для работы с приложением из предыдущего раздела.

  1. Для пользовательского интерфейса требуется отображать список учащихся в таблице, ФИО должно быть ссылкой на просмотр детальной информации об учащемся.

  2. Детальная информация об учащемся выводить так же в таблице.

  3. Для API интерфйеса используйте префикс api в пути для обрабтчиков, а для пользовательского - ui.

Для проверки API интерфейса используйте библиотеку requests.