В данной статье вы узнаете, как использовать Flask и React для создания full-stack приложений, которые легко масштабируются.
Мы рассмотрим следующие темы:
- Обзор проекта, созданного с помощью Flask и React
- Требования для Flask + React проекта
- Что такое Flask?
- Что такое React?
- Создание бэкенда для Flask API
- Зависимости Flask API
- Тестирование Flask API с помощью POSTMAN
- React UI — Пользовательский интерфейс
- Собираем и запускаем Flask проект
В данном уроке будет рассказано, как использовать Flask и React для создания масштабируемых и готовых к использованию проектов. Flask — это популярный веб-фреймворк на Python, используемый для обеспечения всего функционала бэкенда, таких как аутентификация, интерфейс базы данных и управление пользователями.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
В этой архитектуре React обрабатывает пользовательский интерфейс (UI) и взаимодействует с Flask отдельно от бэкенда, используя безопасные запросы. Чтобы сделать эту статью более полезной, мы упомянем несколько проектов с открытым исходным кодом, доступных для скачивания с Github по лицензии MIT.
На заметку: Все ресурсы из данной статьи доступны для загрузки с Github. Админ-Панель на React настроена для работы с простым Flask API Server.
- Flask API Server — проект с открытым исходным кодом (лицензия MIT);
- React Datta Able — панель-управления на React;
- React Berry Dashboard — панель-управления на React;.
Обзор проекта, созданного с помощью Flask и React
Full-stack проекты могут быть структурированы с помощью различных способов и паттернов. Ниже будут представлены два наиболее популярных паттерна:
Бэкенд + SPA (одностраничное приложение) — в этой конфигурации бэкенд Flask построен по старому доброму паттерну MVC, где файлы обслуживаются из бэкенда, а приложение React обеспечивает взаимодействие с пользователями. Данная модель, была когда-то очень популярна, но уже забыта, потому что из-за смешанного характера технологий их было трудно расширить.
Двухуровневая архитектура — этот паттерн функционально и физически отделяет пользовательский интерфейс (UI) React от бэкенда Flask и использует мост связи через API, предоставляемый сервером. Эта конструкция имеет несколько преимуществ по сравнению с предыдущим решением:
- Пользовательский интерфейс (UI) и бэкэнд можно разрабатывать и тестировать как отдельные объекты;
- Более простое развертывание, или деплоймент;
- При необходимости пользовательский интерфейс (UI) может использовать тестовый API бэкенда (например если готовится новая версия).
Эта статья будет посвящена второму паттерну, двухуровневой архитектуре, где Flask API отделен от React UI.
Далее представлен примерный поток проекта:
- Запускается сервер Flask и открывается API;
- React UI загружается в браузер пользователя;
- React инициирует вход в систему и получает учетные данные, предоставленные пользователем;
- React отправляет учетные данные пользователя на API сервер;
- Flask API проверяет учетные данные и генерирует JWT токен;
- React UI сохраняет информацию о пользователе и его JWT токен;
- Доступ к админке предоставляется до тех пор, пока пользователь не выйдет из системы.
Требования для Flask + React проекта
Для успешной сборки нашего full-stack проекта, несколько инструментов и библиотек должны быть уже установлены и доступны в терминале.
- GIT — инструмент командной строки для управления версиями;
- Python 3 — язык программирования, на котором работает Flask;
- Node JS — используется для привлечения в наш мир магии React;
- Yarn — используется для установки Node JS пакетов;
- Современный редактор кода. К примеру, VsCode или PyCharm;
- Возможность работать в терминале и писать системные команды;
- PIP (поставляется с Python3) — используется для установки пакетов Python.
Что такое Flask?
Flask — это популярный веб-фреймворк для Python, предназначенный для быстрого и простого создания проекта с возможностью масштабирования до сложных приложений. Flask можно использовать при создании простых одностраничных сайтов, а также при разработке API и сложных проектов для электронной коммерции.
Используя Flask, разработчик может свободно структурировать кодовую базу без ограничений, а также устанавливать только те библиотеки, которые он действительно использует. Самый простой способ установить Flask это использовать PIP, официальный менеджер пакетов, поставляемый вместе с Python.
1 |
$ pip install Flask |
Во время инсталляции также устанавливается базовый набор основных зависимостей которые нужны в Flask:
- Werkzeug — имплементирует WSGI, стандартный интерфейс Python между приложениями и серверами;
- Jinja — это язык шаблонов, который делает рендеринг страниц для обслуживаемых приложением;
- MarkupSafe поставляется вместе с Jinja. Он экранирует подозрительный ввод данных от пользователя при рендеринге шаблонов, чтобы избежать SQL-инъекций или XSS атак;
- ItsDangerous — надежно подписывает данные для обеспечения их целостности. Это используется для защиты куки сессии в Flask;
- Click — это фреймворк для написания приложений командной строки.
После завершения установки можно открыть редактор и написать небольшой код для нашего первого Flask приложения:
1 2 3 4 5 6 |
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Привет от Flask!' |
Что такое React?
В 2021 году статистика показывает, что React используется в качестве основной технологии при разработке фронтенда, вытесняя другие фреймворки, такие как Vue, Angular или Svelte. React активно поддерживается и развивается силами Facebook, а также широко используется крупными компаниями, многими разработчиками и open-source энтузиастами.
React можно использовать в старых проектах через импорт из CDN или начать новый проект с помощью инструмента командной строки CRA (create-react-app). В нашем примере мы будем использовать шаблон с открытым исходным кодом, в котором код для аутентификации добавлен поверх существующего проекта, изначально созданного с помощью инструмента CRA. Для получения дополнительной информации о React, пожалуйста можете ознакомиться со следующими ресурсами:
- Официальная документация — интеграция React в старый проект;
- Создание нового React приложения — очень неплохой туториал.
Создание бэкенда для Flask API
Flask отлично подходит для написания чего-то полезного за небольшой промежуток времени. Наш бэкенд-сервер должен предоставлять простую службу аутентификации с использованием веб токенов JWT, которая предоставляет несколько основных методов:
/api/users/register
: создание нового пользователя;/api/users/login
: аутентификация существующего пользователя;/api/users/logout
: выход пользователя из системы;/api/users/edit
: редактирование информации, связанной с зарегистрированным пользователем.
Учитывая эти API требования, следует уточнить некоторые другие аспекты: тип базы данных, используемые библиотеки REST и JWT, и, конечно, структуру проекта. Чтобы облегчить процесс, мы выберем SQLite, но у нас будет возможность миграции на более сложные СУБД, такие как MySQL и PostgreSQL.
Зависимости Flask API
flask-restx
— используется для маршрутизации API;Flask-JWT-Extended
— управление JWT токенами;Flask-SQLAlchemy
— абстрактный интерфейс для базы данных.
Мы будем использовать паттерн app factory, где функциональность API изолирована в отдельной папке и построена как Python пакет. Возможная структура проекта показана ниже:
1 2 3 4 5 6 7 8 9 |
api-server-flask/ ├── api | ├── __init__.py │ ├── config.py # настройки проекта │ ├── models.py # таблицы базы данных │ └── routes.py # реализует API маршруты | ├── requirements.txt # зависимости проекта ├── run.py # точка запуска проекта |
Давайте напишем код для маршрутов, то есть самой важной части API сервера. Далее представлен наиболее важный код.
Routes.py — Импорты необходимые пакеты
1 2 3 |
from flask_restx import Api, Resource, fields import jwt from .models import db, Users |
Routes.py — Инициализация API
1 2 3 |
... rest_api = Api(version="1.0", title="Users API") ... |
Routes.py — Инициализация валидатора для проверки данных из формы регистрации.
1 2 3 4 5 6 7 |
signup_model = rest_api.model( 'SignUpModel', { "username": fields.String(required=True, min_length=2, max_length=32), "email": fields.String(required=True, min_length=4, max_length=64), "password": fields.String(required=True, min_length=4, max_length=16) } ) |
Routes.py — Обработчик данных при регистрации нового пользователя.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@rest_api.route('/api/users/register') class Register(Resource): """ Регистрация нового пользователя в базе данных с использованием подели `signup_model`. """ @rest_api.expect(signup_model, validate=True) def post(self): req_data = request.get_json() _username = req_data.get("username") _email = req_data.get("email") _password = req_data.get("password") user_exists = Users.get_by_email(_email) if user_exists: return {"success": False, "msg": "Email already taken"}, 400 new_user = Users(username=_username, email=_email) new_user.set_password(_password) new_user.save() return { "success": True, "userID": new_user.id, "msg": "Пользователь успешно зарегистрирован" }, 200 |
Приведенные выше фрагменты кода (валидатор, обработчик данных) должны быть повторены для всех методов API.
Финальный код Routes.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
from flask_restx import Api, Resource, fields import jwt from .models import db, Users rest_api = Api(version="1.0", title="Users API") signup_model = rest_api.model( 'SignUpModel', { "username": fields.String(required=True, min_length=2, max_length=32), "email": fields.String(required=True, min_length=4, max_length=64), "password": fields.String(required=True, min_length=4, max_length=16) } ) @rest_api.route('/api/users/register') class Register(Resource): """ Регистрация нового пользователя в базе данных с использованием подели `signup_model`. """ @rest_api.expect(signup_model, validate=True) def post(self): req_data = request.get_json() _username = req_data.get("username") _email = req_data.get("email") _password = req_data.get("password") user_exists = Users.get_by_email(_email) if user_exists: return {"success": False, "msg": "Email already taken"}, 400 new_user = Users(username=_username, email=_email) new_user.set_password(_password) new_user.save() return { "success": True, "userID": new_user.id, "msg": "Пользователь успешно зарегистрирован" }, 200 |
Тестирование Flask API с помощью POSTMAN
Когда API запущен и работает, мы можем использовать POSTMAN, это популярный и бесплатный инструмент для тестирования точек входа от API. Мы предполагаем, что Flask API запущен на порту 5000, а метод регистрации полностью прописан и работает.
Postman — Создаем запрос со следующими свойствами:
- POST-запрос по адресу
"http://localhost:5000/api/users/register"
- Заголовок
Content-type
:"application-json"
- Тело запроса (данные пользователя для регистрации):
user/password
иemail
Содержимое из тела запроса предоставляет данные для регистрации нового пользователя.
Полученный ответ от API после регистрации.
На этом этапе пользователь уже создан в базе данных, и мы можем пройти аутентификацию и продолжить работу над нашим full-stack проектом.
React UI — Пользовательский интерфейс
React часть этого руководства написана поверх проекта с открытым исходным кодом, клонированного с Github, а именно React Datta Able, которая является действительно красивой и красочной Панели-Управления, предоставленной студией CodedThemes.
Первоначальный проект это по сути React шаблон, который будет улучшен с помощью нескольких простых особенностей:
- Удобный процесс аутентификации пользователя, совместимый с Flask API;
- Возможности: Входа, Выхода и Регистрации;
- Неавторизованные пользователи будут перенаправлены на страницу входа в систему;
- Панель-управления видна только аутентифицированным пользователям.
Проект имеет действительно красивый дизайн. Давайте загрузим готовую сборку этого React шаблона и позже добавим необходимый код для расширения всего функционала.
1 2 |
$ git clone https://github.com/codedthemes/datta-able-free-react-admin-template.git $ cd datta-able-free-react-admin-template/template |
Установка зависимостей — через NPM или Yarn
1 2 3 |
$ npm i // ИЛИ $ yarn |
React Datta Able — Запуск проекта в режиме разработки
1 2 3 |
$ npm run start // ИЛИ $ npm start |
Чтобы создать новый функционал, сперва необходимо обновить зависимости проекта, добавив несколько полезных библиотек:
- Formik — используется для управления формами регистрации;
- Axios — используется для коммуникации между браузером пользователя и API.
Как только новые зависимости будут правильно установлены, мы сможем продолжить работу над кодом.
Найстройка проекта — API точки входа
Приложение будет использовать общий набор переменных, импортируемых в различные места, такие как страница аутентификации, выход пользователя и т.д.
Для упрощения это процесса — было бы неплохо определить все переменные в одном файле: src/config/constant.js
1 2 3 4 |
export const BASENAME = ''; // не добавляйте '/' в конце BASENAME export const BASE_URL = '/app/dashboard/default'; export const BASE_TITLE = ' | React Datta Able '; export const API_SERVER = 'http://localhost:5000/api/'; |
Наиболее важное значение сохраняет переменная API_SERVER
, по сути это адрес нашего API. Когда проект будет запущен в рабочем режиме, то этот адрес должен быть обновлен соответствующим образом с адресом публичного API который будет содержать нормальный домен.
Создание компонента Guest Guard (Гостевой охранник)
Этот компонент отвечает за определение того, аутентифицирован ли текущий пользователь или нет. Простые гости перенаправляются на страницу входа, а аутентифицированные пользователи получают доступ ко всем приватным страницам.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import React from 'react'; import { Redirect } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { BASE_URL } from '../../config/constant'; const GuestGuard = ({ children }) => { const account = useSelector((state) => state.account); const { isLoggedIn } = account; if (isLoggedIn) { return <Redirect to={BASE_URL} />; } return <React.Fragment>{children}</React.Fragment>; }; export default GuestGuard; |
Создаем Redux-хранилище, управляющее состоянием пользователя
Приложение React должно быть способно принимать решения на основе информации, связанной с текущим пользователем. Хранилище redux-store
предоставляет эту информацию простым способом, используя несколько переменных и объектов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
export const initialState = { token: '', isLoggedIn: false, isInitialized: false, user: null }; const accountReducer = (state = initialState, action) => { switch (action.type) { case ACCOUNT_INITIALIZE: { const { isLoggedIn, user, token } = action.payload; return { ...state, isLoggedIn, isInitialized: true, token, user }; } case LOGIN: { const { user } = action.payload; return { ...state, isLoggedIn: true, user }; } case LOGOUT: { return { ...state, isLoggedIn: false, token: '', user: null }; } default: { return { ...state }; } } }; |
Переменные, связанные с текущим пользователем, должны обновляться на основе действий, выполняемых в сессии:
- Гостевой доступ: пользовательская сессия не существует — Null, состояние переменной
isLoggedIn
равно false; - Вход: пользователь успешно прошел аутентификацию. Содержимое переменной
isLoggedIn
становится true; - Выход: все данные сессии удаляются, и содержимое переменной
isLoggedIn
снова становится false.
На данном этапе — React UI можно использовать для регистрации и аутентификации пользователей.
Собираем и запускаем Flask проект
Весь приведенный выше код уже представлен на Github в двух отдельных проектах:
- Flask API Server — простой API сервер с открытым исходным кодом;
- React Datta Able — улучшенная версия с JWT аутентификацией.
Шаг №1 — Клонирование исходного кода.
1 2 |
$ git clone https://github.com/app-generator/api-server-flask.git $ cd api-server-flask |
Шаг №2 — Установка зависимостей с помощью виртуальной среды.
1 2 3 4 |
$ virtualenv env $ source env/bin/activate $ $ pip3 install -r requirements.txt |
Шаг №3 — Настройка среды разработки.
1 2 |
$ export FLASK_APP=run.py $ export FLASK_ENV=development |
Шаг №4 — Создание SQLite базы данных и её таблиц.
1 2 3 |
$ flask shell >>> from api import db >>> db.create_all() |
Шаг №5 — Запуск API сервера
1 2 |
$ flask run // API сервер запустился на http://localhost:5000 |
На этом этапе наш API сервер должен быть запущен.
Сборка и запуск фронтенда на React UI
Шаг №1 — Клонирование исходного кода.
1 2 |
$ git clone https://github.com/app-generator/react-datta-able-dashboard.git $ cd react-datta-able-dashboard |
Шаг №2 — Установка зависимостей.
1 2 3 |
$ npm i // ИЛИ $ yarn |
Шаг №3 — Запуск в режиме разработчика.
1 2 3 4 |
$ npm run start // ИЛИ $ yarn start // React UI запускается на http://localhost:3000 |
Браузер должен отобразить страницу для входа. Теперь можно зарегистрировать новых пользователей и пройти аутентификацию.
Спасибо за прочтение!
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»