🐍 Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask
Покажем, как писать маршруты и функции представления, использовать шаблоны и работать с базами данных. В конце статьи – 10 мини-проектов, от модулей инвентаризации и учета товаров до приложения для хранения заметок и блога.
Flask – компактный фреймворк для быстрой разработки веб-приложений. Он предоставляет минимальную необходимую функциональность и не навязывает никаких строгих правил в отношении структуры и архитектуры приложения (как это делает Django).
Flask универсален – на его основе можно создавать сложные приложения и API, и в то же время он идеально подходит для разработки небольших проектов. Самый большой плюс Flask – на нем очень просто реализовать генератор статических сайтов.
Основные преимущества Flask:
- Минималистичность. Flask отличается небольшим размером – в нем есть все самое необходимое и нет ничего лишнего.
- Гибкость. Фреймворк не диктует определенных правил и позволяет разработчику сохранить полный контроль над структурой приложения.
- Простота в использовании. Он имеет несколько встроенных функций, которые позволяют сразу начать создавать полноценные веб-приложения, даже если у вас нет опыта в веб-разработке на Python. Например, у Flask есть встроенный сервер, поддержка сессий, обработчик форм, шаблонизатор.
- Интеграция с дополнительными библиотеками. Фреймворк очень просто интегрируется с многочисленными библиотеками, которые расширяют его функциональность. Это позволяет создать гибкий, масштабируемый проект для любой сферы.
- Простота тестирования. У Flask есть встроенный тестовый клиент, который максимально упрощает тестирование и отладку.
Установка
Flask лучше всего устанавливать в виртуальное окружение – это позволяет избежать появления ошибок, связанных с конфликтами версий различных библиотек и модулей. Выполните в cmd:
Перейдите в только что созданную директорию:
Активируйте окружение:
И установите Flask:
Активировать виртуальное окружение нужно перед каждым сеансом работы с Flask.
Простейшее приложение на Flask
Напишем приложение, которое будет выводить традиционное приветствие Hello, World! в браузере. Сохраните этот код в файле app.py в директории fproject:
Этот код создает объект приложения Flask с помощью класса Flask и присваивает его переменной app. Декоратор @app.route('/')
устанавливает маршрут для
главной страницы нашего приложения, а метод def hello()
определяет, что будет отображаться на этой странице.
if
__name__ == '__main__':
проверяет,
запускается ли данный файл как самостоятельное приложение, или импортируется как модуль. В
нашем случае он запускается как независимое приложение, поэтому вызывается метод app.run(), который запускает веб-сервер Flask.
Запустите приложение в командой строке:
Откройте адрес http://localhost:5000/ в браузере:
Flask по умолчанию использует порт 5000. При желании его можно изменить на более привычный 8000:
Кроме того, можно включить режим отладки – тогда все возникающие ошибки будут отображаться на странице браузера, а при внесении любых изменений в файлы проекта сервер будет автоматически перезагружаться:
Для остановки сервера нажмите Ctrl+C.
Маршруты в Flask
Маршруты – это URL-адреса, по которым пользователи могут открывать определенные
страницы (разделы) веб-приложения. Маршруты в Flask определяются с помощью декоратора
@app.route()
. Для каждого маршрута можно
написать отдельную функцию представления, которая будет выполнять какие-то действия при переходе по определенному адресу. Рассмотрим пример:
Сохраните код, запустите приложение, последовательно откройте адреса:
Переменные в маршрутах
В URL можно передавать различные значения. Запустите этот код и перейдите по адресу, например, http://localhost:5000/user/EvilAdmin
Имя пользователя, переданное в качестве переменной, будет показано на странице:
А так можно передать в маршруте целое число:
Перейдите по адресу, например, http://localhost:5000/user/5:
GET- и POST-запросы
GET и POST – это HTTP-запросы, которые используются для отправки данных между клиентом и сервером.
GET-запрос применяют для получения данных от сервера. При выполнении GET-запроса клиент отправляет запрос на сервер, а сервер возвращает запрошенную информацию в ответ. GET-запросы могут содержать параметры в URL-адресе, которые используются для передачи дополнительных данных.
POST-запрос используют для отправки данных на сервер. При выполнении POST-запроса клиент отправляет данные на сервер, а сервер их обрабатывает. POST-запросы обычно применяют для отправки форм, с данными из которых нужно что-то сделать на бэкенде.
Рассмотрим простейший пример обработки формы авторизации. Базы данных для хранения учетных записей у нас пока нет, поэтому в приведенном ниже коде мы пропустим всю функциональность для проверки корректности логина и пароля (мы рассмотрим этот вопрос позже, в одном из заданий):
Маршрут @app.route('/login', methods=['GET', 'POST'])
обрабатывает и POST, и GET-запросы: в первом случае он отправит
данные на сервер, во втором – просто выведет страницу с формой авторизации.
Для вывода формы на странице сделаем простейший шаблон. Этот код нужно сохранить в файле login.html, в директории templates (в этой папке Flask по умолчанию ищет шаблоны):
Никакие CSS стили к шаблону не подключены, поэтому он выглядит не слишком привлекательно. Но шаблон работает, а форма получает логин и пароль:
Шаблонизатор Jinja2
Шаблоны в Flask используются для динамического формирования веб-страниц. Шаблоны представляют собой HTML страницы, в которые можно передавать любые данные с бэкенда. К шаблонам можно подключать любые CSS-фреймворки типа Bootstrap и Tailwind, и любые JS-скрипты.
Поведением шаблонов управляет шаблонизатор Jinja2 – он предоставляет функциональность для создания условий, циклов, макросов, наследования и блоков. Главные преимущества шаблонизатора:
- Может проводить различные операции с контентом самостоятельно, не обращаясь к бэкенду.
- Обеспечивает наследование дизайна и стилей от базового шаблона.
Наследование работает так:
- Базовый шаблон, который обычно называется base.html, содержит общую разметку для сайта.
- В base.html подключаются локальные и CDN-фреймворки (CSS, JS), задаются фоновые изображения и фавикон.
- Дочерние шаблоны наследуют этот базовый шаблон и дополняют его своим собственным контентом.
Продемонстрируем наследование на примере. Сохраните в папке templates два файла. Это содержимое файла base.html – в нем подключается CSS-фреймворк Bootstrap, кастомные стили custom.css из статической папки static, иконки Font Awesome:
Шаблон base.html также содержит верхнее меню для навигации по сайту – это меню будут наследовать все дочерние шаблоны. Вот пример дочернего шаблона about.html:
Фон страницы шаблонизатор берет из файла static/customs.css:
А код для вывода страницы выглядит так:
Запустите приложение, откройте адрес http://localhost:5000/about:
Работа с базой данных
Для работы с базами данных в Flask удобно использовать ORM SQLAlchemy. Как уже упоминалось в предыдущей главе о SQLite, ORM играет роль своеобразной прослойки между приложением и СУБД SQLite, и позволяет работать с базами без использования языка SQL. Надо заметить, что работать с базами данных в SQLAlchemy немного сложнее, чем в Django ORM, но гораздо проще, чем в чистом Python.
Начнем с установки SQLAlchemy в виртуальное окружение:
В SQLAlchemy основой для создания таблиц в базе данных служат модели (специальные классы). Поля классов определяют структуру таблицы, которая будет использоваться для хранения информации в базе данных. В полях классов можно задавать типы данных, которые соответствуют типам данных в БД, например, String для хранения строк, Integer для целых чисел, Float для плавающих чисел и т.д.
SQLAlchemy, как и другие ORM, очень упрощает создание связей между таблицами. В приведенном ниже примере используется связь один ко многим (ForeignKey), поскольку у одного исполнителя может быть несколько альбомов, а в одном альбоме всегда будет несколько треков:
Сохраните этот код в файле models.py – мы будем импортировать модели из него в главный файл приложения app.py и в скрипт create_db.py, который создает базу данных и заполняет ее тестовой информацией.
Код для create_db.py будет следующим:
Этот код наглядно демонстрирует, как именно создаются записи, и какие между ними существуют связи. Чтобы создать и заполнить базу, запустите файл в активированном виртуальном окружении:
В реальных приложениях базу данных удобнее заполнять, например, с помощью модуля csv – мы рассмотрим этот метод ниже, в одном из заданий.
Главный файл приложения app.py выглядит так:
Шаблон songs.html использует тот же самый базовый base.html, что и предыдущий пример:
После создания шаблона можно запустить приложение:
Практика
Задание 1
Напишите Flask-приложение, которое выводит в шаблон index.html приветствие для пользователя. Приветствие зависит от времени суток:
- С 6:00 до 12:00 – «Доброе утро»
- С 12:00 до 18:00 – «Добрый день»
- С 18:00 до 24:00 – «Добрый вечер»
- С 00:00 до 6:00 – «Доброй ночи»
Пример:
Код для app.py выглядит так:
Для вывода приветствия используются шаблоны base.html и index.html.
Задание 2
Напишите Flask-приложение, которое с помощью шаблона выводит пронумерованный список дел.
Пример:
Это код приложения app.py:
Нумерацию в Jinja2
легко реализовать с помощью loop.index
:
Задание 3
Напишите app.py и шаблон welcome.html, которые выводят различный контент для пользователей с разными правами доступа:
- Админ имеет полный доступ.
- Модератор может редактировать записи и комментарии.
- Рядовой пользователь может создавать записи от своего имени и просматривать френдленту.
Пример:
В приложении app.py можно определить только маршрут, вся функциональность по определению уровней доступа находится в шаблоне:
Задание 4
Напишите скрипт для создания и заполнения базы данных SQLite данными о книгах из файла books.json, а также app.py и шаблоны, которые выводят:
- Карточки с информацией о книгах.
- Карточку отдельной книги.
Пример:
Напишем модель Book и скрипт, который создает и заполняет базу из json-файла. Затем создадим app.py с двумя маршрутами – для вывода всех книг, и для вывода отдельной книги:
Задание 5
Для онлайн-магазина нужно написать модуль, который поможет сотрудникам сделать инвентаризацию. Приложение состоит из базы данных, в которой таблицы связаны сложными отношениями:
- Каждый производитель (Manufacturer) поставляет несколько типов товаров (Category) – ноутбуки, наушники, смартфоны и так далее.
- Одну и ту же категорию товаров могут производить несколько компаний.
- В каждой категории может быть множество товаров (Item).
Нужно реализовать вывод всех товаров по поставщикам и по категориям. Все данные о товарах находятся в файле info.csv.
Пример:
Файл models.py, описывающий структуру базы данных, выглядит так:
Для заполнения базы данными из файла info.csv напишем скрипт. Приложение использует 4 шаблона:
За вывод всех товаров определенного производителя в отдельной категории отвечает эта функция:
Задание 6
Для супермаркета нужно написать веб-приложение, которое выводит список товаров на складе и позволяет добавлять новые.
Пример:
Приложение состоит из файлов app.py, create_db.py и models.py. Для добавления новых товаров используется шаблон add.html и маршрут/функция add:
Задание 7
Для ветеринарной клиники нужно написать модуль учета пациентов. В приложении должны быть функции добавления, редактирования и удаления карточек.
Пример:
Начнем с создания базы данных на основе моделей. Функции add_patient, edit_patient, delete_patient реализованы в приложении app.py. Шаблоны add.html и edit.html обеспечивают добавление и редактирование карточек:
Задание 8
Напишите модуль аутентификации для Flask-приложения. Необходимо реализовать:
- регистрацию;
- проверку учетных данных при входе;
- перенаправление на страницу профиля.
Пример:
Проект включает в себя файлы app.py, create_db.py и models.py. Кроме того, модуль использует шаблоны:
После регистрации и входа пользователь перенаправляется на страницу своего профиля:
Задание 9
Напишите веб-приложение для хранения заметок. Необходимо реализовать набор CRUD операций – вывод, добавление, редактирование и удаление заметок. При создании базы данных следует учесть, что заметка может относиться только к одной категории, а в категории может быть множество заметок. На главной странице выводятся все заметки, причем текст ограничивается первыми 300 символами. Нажатие на ссылку «Далее» открывает страницу с полным текстом заметки.
Пример:
База данных для приложения создается с помощью скрипта create_db.py на основе моделей.
CRUD операции
описаны в app.py. При нажатии на
название категории шаблон и маршрут category
выводят все заметки, относящиеся
к данной теме.
Задание 10
Напишите Flask приложение для ведения блога. Каждая запись может иметь несколько тегов, но должна относиться к одной категории. Как и в предыдущем задании, нужно реализовать просмотр отдельных записей, добавление, редактирование и удаление постов. При выводе всех записей, а также записей по категориям и тегам посты должны отображаться в порядке убывания даты, т.е. самые новые находятся сверху.
Пример:
Прежде всего разработаем модели Tag, Category и Post, а затем создадим на их основе базу данных при помощи скрипта.
Приложение использует следующие шаблоны:
CRUD операции реализованы в главном файле приложения app.py. Чтобы самые свежие
записи выводились первыми, в models.py мы
определили метод newest_first
. При нажатии на ссылку «Читать»
выводится полный текст записи:
Подведем итоги
Мы рассмотрели основные приемы разработки простых веб-приложений на основе фреймворка Flask:
- Создание маршрутов и функций представления.
- Получение и обработку данных с фронтенда.
- CRUD операции.
- Основные возможности шаблонизатора Jinja2.
При создании приложений Flask для получения данных с фронтенда обычно используются формы WTF Forms. В этой статье при решении заданий намеренно использовались HTML-формы – так процесс передачи и обработки данных выглядит максимально понятно.
В следующей статье будем изучать NumPy.
Содержание самоучителя
- Особенности, сферы применения, установка, онлайн IDE
- Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
- Типы данных: преобразование и базовые операции
- Методы работы со строками
- Методы работы со списками и списковыми включениями
- Методы работы со словарями и генераторами словарей
- Методы работы с кортежами
- Методы работы со множествами
- Особенности цикла for
- Условный цикл while
- Функции с позиционными и именованными аргументами
- Анонимные функции
- Рекурсивные функции
- Функции высшего порядка, замыкания и декораторы
- Методы работы с файлами и файловой системой
- Регулярные выражения
- Основы скрапинга и парсинга
- Основы ООП: инкапсуляция и наследование
- Основы ООП: абстракция и полиморфизм
- Графический интерфейс на Tkinter
- Основы разработки игр на Pygame
- Основы работы с SQLite
- Основы веб-разработки на Flask
- Основы работы с NumPy
- Основы анализа данных с Pandas