1. Визуализация шаблона и использование переменных
Создав просто веб-приложение на Flask, я решил попробовать использование шаблонов. Для этого, я создалf файл app2.py.
В него добавляем следующее:
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def hello(): return render_templ
В этом блоке кода мы импортируем класс Flask и функцию render_template()
из пакета flask. Мы используем класс Flask для создания экземпляра приложения Flask с именем app. Затем мы определяем функцию просмотра (которая является функцией Python, которая возвращает ответ HTTP) с именем hello()
, используя декоратор app.route()
, который преобразует обычную функцию в функцию просмотра. Эта функция представления использует функцию render_template()
для визуализации файла шаблона с именем index.html.
Затем нам нужно будет создать файл шаблона index.html в каталоге с именем templates. Flask ищет шаблоны в каталоге templates, который называется шаблонами, поэтому имя важно. Для этого выполним следующую команду, чтобы создать каталог шаблонов:
mkdir templates
Затем откроем файл с именем index.html и добавим следующий HTML код:
FlaskApp Hello World!
Welcome to FlaskApp!
Здесь мы устанавливаем заголовок, добавляем Hello World! сообщение в виде заголовка h1 и создаем сообщение Welcome to FlaskApp!
как заголовок h2. Далее запускаем наше приложение. (как это сделать говорилось выше)
Оставим сервер запущенным и откроем файл app2.py для редактирования. Импортируем модуль datetime
из стандартной библиотеки Python и отредактируем функцию index()
, чтобы файл выглядел следующим образом:
import datetime from flask import Flask, render_template app = Flask(__name__) @app.route('/') def hello(): return render_template('index.html', utc_dt=datetime.datetime.utcnow())
Здесь мы импортировали модуль datetime и передали в шаблон index.html переменную с именем utc_dt
со значением datetime.datetime.utcnow()
, которое является текущей датой и временем в формате UTC.
Затем, чтобы отобразить значение переменной на странице индекса, откроем файл index.html для редактирования. Отредактируем файл, чтобы он выглядел следующим образом:
FlaskApp Hello World!
Welcome to FlaskApp!
{{ utc_dt }}
Мы добавили заголовок h2 со специальным разделителем {{...}}
для печати значения переменной utc_dt
. Откроем браузер и перейдём на главную страницу:
Теперь мы создали страницу индекса с шаблоном HTML в приложении Flask, отрисовали шаблон, передали и отобразили значение переменной. Затем мы избежим повторения кода, используя наследование шаблонов.
2. Использование механизма наследования шаблонов
На этом этапе мы создадим базовый шаблон с содержанием, которым можно будет поделиться с другими шаблонами. Мы отредактируем свой шаблон индекса, чтобы он унаследовал от базового шаблона. Затем мы создадим новую страницу, которая будет служить страницей «О приложении», где пользователи смогут найти дополнительную информацию о вашем приложении.
Для этого, создадим base.html и пропишем следующий код:
{% block title %} {% endblock %} - FlaskApp nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; }
{% block content %} {% endblock %}
Большая часть кода в этом файле представляет собой стандартный HTML код, заголовок, некоторые стили для ссылок навигации, панель навигации с двумя ссылками, одна для страницы индекса, другая для еще не созданной страницы «О программе», а также div для содержание страницы. (Ссылки пока не работают; на следующем шаге будет показано, как создавать ссылки между страницами). Однако, следующие выделенные части относятся к шаблонизатору Jinja:
• {% block title %} {% endblock %}
: блок, который служит заполнителем для заголовка. Позже вы будете использовать его в других шаблонах, чтобы задать собственный заголовок для каждой страницы в приложении, не переписывая каждый раз весь раздел.
• {% block content %} {% endblock %}
: другой блок, который будет заменен содержимым в зависимости от дочернего шаблона (шаблона, наследуемого от base.html), который заменит его.
Теперь, когда у нас есть базовый шаблон, мы можем воспользоваться им, используя наследование. Откроем файл index.html и затем заменим его содержимое следующим:
{% extends 'base.html' %} {% block content %}{% block title %} Index {% endblock %}
Hello World!
Welcome to FlaskApp!
{{ utc_dt }}
{% endblock %}
Здесь мы используем тег {% extends %}
для наследования от шаблона base.html. Затем мы расширяем его, заменяя блок содержимого в базовом шаблоне тем, что находится внутри блока содержимого в предыдущем блоке кода.
Этот блок содержимого содержит тег h1 с текстовым индексом внутри основной надписи, который, в свою очередь, заменяет исходную основную надпись в шаблоне base.html текстовым индексом, так что полный заголовок становится индексом — FlaskApp. Таким образом, мы можем избежать повторения одного и того же текста дважды, поскольку он работает как заголовок страницы, так и заголовок, который появляется под панелью навигации, унаследованной от базового шаблона. Затем у нас есть еще несколько заголовков: один заголовок h1 с текстом Hello World!, заголовок h2 и заголовок h3, содержащий значение переменной utc_dt
.
Наследование шаблонов дает нам возможность повторно использовать HTML код, который есть в других шаблонах (в данном случае base.html), без необходимости повторять его каждый раз, когда это необходимо. Сохраним и обновим страницу индекса в браузере. Страница будет выглядеть следующим образом:
Затем мы создаем страницу «About». Открываем файл app2.py, чтобы добавить новый маршрут и добавляем следующее:
# ... @app.route('/about/') def about(): return render_template('about.html')
Здесь используется декоратор app.route()
для создания функции просмотра с именем about()
. В нем мы возвращаем результат вызова функции render_template()
с именем файла шаблона about.html в качестве аргумента.
Откроем файл шаблона с именем about.html для редактирования и добавьте следующий код:
{% extends 'base.html' %} {% block content %}{% block title %} About {% endblock %}
FlaskApp is a Flask web application written in Python.
{% endblock %}
Здесь мы наследуем базовый шаблон с помощью тега extends, заменяем блок содержимого базового шаблона тегом h1, который также служит заголовком страницы, и добавляем тег h3 с некоторой информацией о приложении.
Когда сервер разработки запущен, перейдем по следующему URL адресу в своем браузере:
http://127.0.0.1:5000/about
Мы увидим следующее:
<img src="http://is42-2018.susu.ru/batalovaryu/wp-content/uploads/sites/9/2021/12/4.png" alt="" width="417" height="290" class="aligncenter size-full wp-image-989" /
Мы создали базовый шаблон и использовали его на своей индексной странице и на странице сведений, чтобы избежать повторения кода.
3. Связывание страниц
На этом этапе мы свяжем страницы в шаблонах с помощью вспомогательной функции
url_for()
. Мы добавим две ссылки на панель навигации в свой базовый шаблон, одну для главной страницы и другую для страницы «About».
Сначала откроем базовый шаблон для редактирования и внесите следующие изменения:
{% block title %} {% endblock %} - FlaskApp nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; }
{% block content %} {% endblock %}
Здесь мы используем специальную функцию url_for()
, которая возвращает URL адрес функции просмотра, которую мы ему передаем. Первая ссылка ссылается на маршрут функции просмотра hello()
(которая является страницей индекса). Вторая ссылка указывает на маршрут функции просмотра about()
. Обратите внимание, что мы передаем имя функции просмотра, а не маршрут (/ или /about). Использование функции url_for()
для создания URL адресов помогает лучше управлять URL адресами. Если мы жестко запрограммируем URL адреса, наши ссылки сломаются, если мы изменим маршруты. С url_for()
мы можем редактировать маршруты и гарантировать, что ссылки будут работать должным образом. Функция url_for()
также заботится о других вещах, таких как экранирование специальных символов.
Теперь перейдем на главную страницу и попробуем ссылки на панели навигации. Мы увидим, что они работают.
4. Использование условных выражений и циклов
На этом этапе мы будем использовать операторы
if
в своих шаблонах, чтобы управлять тем, что отображать в зависимости от определенных условий. Мы также будем использовать циклы for
для просмотра списков Python и отображения каждого элемента в списке. Мы добавим новую страницу, на которой будут отображаться комментарии в виде списка. Комментарии с четным порядковым номером будут иметь синий фон, а комментарии с нечетным порядковым номером будут отображаться на сером фоне.
Сначала мы создадим маршрут для страницы комментариев. Откроем файл app2.py для редактирования и добавьте следующий маршрут в конец файла:
# ... @app.route('/comments/') def comments(): comments = ['This is the first comment.', 'This is the second comment.', 'This is the third comment.', 'This is the fourth comment.' ] return render_template('comments.html', comments=comments)
В приведенном выше маршруте у нас есть список Python, называемый комментариями, который содержит четыре элемента. Мы возвращаете файл шаблона с именем comments.html в последней строке, передача переменной с именем comments, содержащей список, в файл шаблона.
Затем создадим и откроем новый файл comments.html в каталоге шаблонов для редактирования и добавим следующий код:
{% extends 'base.html' %} {% block content %}{% block title %} Comments {% endblock %}
{% for comment in comments %}{% endblock %}{% endfor %}{{ comment }}
Здесь мы расширяем шаблон base.html и заменяем содержимое блока содержимого. Во-первых, мы используем заголовок h1, который также служит заголовком страницы.
Мы используем цикл Jinja for в строке {% for comment in comments %}
, чтобы просмотреть каждый комментарий в списке комментариев (который сохраняется в переменной комментария). Комментарий отображается в теге (p style="font-size: 24px" {{comment}} /p)
так же, как мы обычно отображаем переменную в Jinja. Мы сигнализируем о завершении цикла for с помощью ключевого слова {% endfor %}
. Это отличается от способа построения циклов for в Python, поскольку в шаблонах Jinja нет специального отступа.
Когда сервер разработки запущен, откроем браузер и перейдем на страницу комментариев:
http://127.0.0.1:5000/comments
Мы увидим следующее:
Давайте откроем файл шаблона comments.html и отредактируйте его, чтобы он выглядел следующим образом:
{% extends 'base.html' %} {% block content %}{% block title %} Comments {% endblock %}
{% for comment in comments %} {% if loop.index %2 == 0 %} {% set bg_color = '#e6f9ff' %} {% else %} {% set bg_color = '#eee' %} {% endif %}{% endblock %}{% endfor %}#{{ loop.index }}
{{ comment }}
С помощью этого нового редактирования мы добавили оператор if
в строку {% if loop.index %2 == 0 %}
. Переменная цикла — это специальная переменная Jinja, которая дает нам доступ к информации о текущем цикле. Здесь мы используем loop.index
, чтобы получить индекс текущего элемента, который начинается с 1, а не с 0, как в списках Python. Оператор if
здесь проверяет, использует ли индекс даже оператор %. Он проверяет остаток от деления номера индекса на 2; если остаток равен 0, это означает, что номер индекса четный, в противном случае номер индекса нечетный. Тег {% set %}
используется для объявления переменной с именем bg_color
. Если порядковый номер четный, мы устанавливаем его на голубоватый цвет, в противном случае, если номер индекса нечетный, мы устанавливаем переменную bg_color
на серый. Затем мы используем переменную bg_color
, чтобы установить цвет фона для тега div
, содержащего комментарий. Над текстом комментария мы используем loop.index
для отображения текущего номера индекса в теге p
.
Сохраним и посмотрим результат:
Кроме того, чтобы отобразить все комментарии, кроме второго, мы можем использовать оператор if
с условием loop.index != 2
, чтобы отфильтровать второй комментарий.
Откроем шаблон комментариев и отредактируем его, чтобы он выглядел следующим образом:
{% extends 'base.html' %} {% block content %}{% block title %} Comments {% endblock %}
{% for comment in comments %} {% if loop.index != 2 %}{% endblock %}{% endif %} {% endfor %}#{{ loop.index }}
{{ comment }}
Здесь мы используем {% if loop.index != 2 %}
, чтобы отображать только те комментарии, которые не имеют индекса 2, что означает все комментарии, кроме второго. Мы также используем жестко запрограммированное значение для цвета фона вместо помощника loop.cycle()
, чтобы упростить задачу, а остальное не изменяется. Мы завершаем оператор if
, используя {% endif %}
. Обновим страницу комментариев, и мы увидим, что второй комментарий не отображается.
Теперь нам нужно добавить ссылку, которая переводит пользователей на страницу комментариев на панели навигации. Откроем базовый шаблон для редактирования и изменим содержимое тега nav, добавив к нему новую ссылку a:
{% block title %} {% endblock %} - FlaskApp nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; }
{% block content %} {% endblock %}
Здесь мы используем помощник url_for()
для ссылки на функцию просмотра comments()
. Теперь на панели навигации будет новая ссылка, которая ведет на страницу комментариев.
5. Использование фильтров
На этом этапе мы узнаем, как использовать фильтры Jinja в своих шаблонах.
Сначала мы преобразуем комментарии на странице комментариев в верхний регистр. Откроем для редактирования шаблон comments.html и отредактируем его, чтобы он выглядел следующим образом:
{% extends 'base.html' %} {% block content %}{% block title %} Comments {% endblock %}
{% for comment in comments %} {% if loop.index != 2 %}{% endblock %}{% endif %} {% endfor %}#{{ loop.index }}
{{ comment | upper }}
Здесь мы расширяем шаблон base.html и заменяем содержимое блока содержимого. Во-первых, мы используем заголовок h1, который также служит заголовком страницы.
Мы используем цикл Jinja for в строке {% for comment in comments %}
, чтобы просмотреть каждый комментарий в списке комментариев (который сохраняется в переменной комментария). Комментарий отображается в теге ((p style = font-size: 24px {{comment}} /p))
так же, как мы обычно отображаем переменную в Jinja. Мы сигнализируем о завершении цикла for с помощью ключевого слова {% endfor %}
. Это отличается от способа построения циклов for в Python, поскольку в шаблонах Jinja нет специального отступа.
Когда сервер разработки запущен, откроем браузер и перейдем на страницу комментариев:
http://127.0.0.1:5000/comments
Фильтры также могут принимать аргументы в круглых скобках. Чтобы продемонстрировать это, воспользуемся фильтром объединения, чтобы объединить все комментарии в списке комментариев.
Откроем шаблон комментариев и отредактируем его, чтобы он выглядел следующим образом:
{% extends 'base.html' %} {% block content %}{% block title %} Comments {% endblock %}
{% for comment in comments %} {% if loop.index != 2 %}{% endblock %}{% endif %} {% endfor %}#{{ loop.index }}
{{ comment | upper }}
{{ comments | join(" | ") }}
Здесь мы добавили теги hr
и div
, где мы объединяем все комментарии в списке комментариев с помощью фильтра join()
. Обновим страницу комментариев, и мы увидим страницу, подобную следующей:
Как видите, список comments отображается с комментариями, разделенными вертикальной чертой, которую мы передали фильтру join()
.
Другой важный фильтр — это безопасный фильтр, который позволяет отображать доверенный HTML код в браузере. Для его реализации откроем шаблон комментариев и отредактируем его, чтобы он выглядел следующим образом:
{% extends 'base.html' %} {% block content %}{% block title %} Comments {% endblock %}
{% for comment in comments %} {% if loop.index != 2 %}{% endblock %}{% endif %} {% endfor %}#{{ loop.index }}
{{ comment | upper }}
{{ "COMMENTS
" }}{{ comments | join("
") }}
Здесь мы добавили значение h1 COMMENTS/h1
и изменили аргумент соединения на тег hr
. Обновим страницу комментариев, и мы увидите страницу, подобную следующей:
Чтобы отобразить HTML теги выше, откроем файл шаблона комментариев и добавим безопасный фильтр:
{% extends 'base.html' %} {% block content %}{% block title %} Comments {% endblock %}
{% for comment in comments %} {% if loop.index != 2 %}{% endblock %}{% endif %} {% endfor %}#{{ loop.index }}
{{ comment | upper }}
{{ "COMMENTS
" | safe }}{{ comments | join("
") | safe }}
Мы можем видеть, что мы также можем объединить фильтры в цепочку, как в строке p{{ comments | join("hr") | safe }}hr
. Каждый фильтр применяется к результату предыдущей фильтрации. Обновим страницу комментариев, и мы увидим, что теги HTML теперь отображаются должным образом:
6. Интеграция Bootstrap
Сейчас мы узнаем, как использовать набор инструментов Bootstrap для стилизации нашего приложения. Добавим панель навигации Bootstrap в базовый шаблон, которая будет отображаться на всех страницах, унаследованных от базового шаблона.
Чтобы использовать Bootstrap, нужно добавить его в базовый шаблон, чтобы мы могли использовать его во всех других шаблонах. Откроем свой шаблон base.html для редактирования и запишем:
{% block title %} {% endblock %} - FlaskApp {% block content %} {% endblock %}
Большая часть приведенного выше кода — это шаблон Bootstrap, необходимый для его использования. У нас есть несколько метатегов, ссылка на файл CSS Bootstrap в разделе head, а внизу у нас есть ссылка на необязательный JavaScript. Выделенные части кода содержат код Jinja, объясненный в предыдущих шагах.
Обратите внимание, как мы используем определенные теги и классы CSS, чтобы указать Bootstrap, как отображать каждый элемент.
В теге nav выше у нас есть тег a
с классом navbar-brand
, который определяет ссылку бренда на панели навигации. Внутри тега ul class = ".navbar-nav"
у нас есть обычные элементы панели навигации внутри тега a
в теге li
.
Когда сервер разработки запущен, откроем страницу индекса в своем браузере:
http://127.0.0.1:5000/
Мы увидим страницу, похожую на следующую:
Теперь мы знаем, как использовать HTML шаблоны в своем веб-приложении Flask. Мы использовали переменные для передачи данных с сервера в шаблоны, чтобы избежать повторения HTML кода мы использовали наследование шаблонов, встроили такие элементы, как условные выражения if и циклы for, а также ссылки между разными страницами. Мы узнали о фильтрах для изменения текста и отображения надежного HTML, а также интегрировали Bootstrap в свое приложение.