📖 Теория: Flask-проект от структуры до REST API
⚡ Кратко
- HTTP методы: GET (read), POST (create), PUT (update), DELETE (delete). GET, PUT, DELETE — идемпотентны.
- REST: stateless, ресурсы по URL, единообразный интерфейс.
- Config: класс
Config→ подклассыDevelopmentConfig,ProductionConfig. - Blueprint:
bp = Blueprint('name', __name__)→app.register_blueprint(bp, url_prefix='/...'). - Application Factory:
def create_app(): app = Flask(__name__); db.init_app(app); return app.
1. Описание проекта — Community Pulse
Community Pulse — интерактивная платформа, где анонимные пользователи могут создавать вопросы на общественно значимые темы и получать мнения других участников.
Основные функции
- Создание вопросов: пользователи формулируют вопросы, на которые можно ответить «согласен» или «не согласен».
- Ответы на вопросы: просмотр списка вопросов и голосование.
- Статистика ответов: для каждого вопроса — счётчик согласных и несогласных.
Технологический стек
| Технология | Назначение |
|---|---|
| Flask | Веб-сервер, маршрутизация запросов |
| Flask-SQLAlchemy | ORM, управление базой данных |
| Alembic (Flask-Migrate) | Управление миграциями БД |
| Pydantic | Сериализация и валидация данных |
2. HTTP методы
HTTP методы — стандартизированные команды, которые клиенты (браузеры, приложения) используют для взаимодействия с сервером. Они определяют тип операции, которую клиент хочет выполнить.
Основные методы (CRUD)
| Метод | CRUD | Идемпотентен? | Описание |
|---|---|---|---|
GET |
Read | Да | Получение данных от сервера. Повторный запрос к тому же URL возвращает тот же результат и не изменяет данные. |
POST |
Create | Нет | Отправка данных для создания нового ресурса. Каждый повторный запрос может создавать новый ресурс. |
PUT |
Update | Да | Полное обновление существующего ресурса по URL. Повторный запрос с теми же данными не меняет состояние повторно. |
PATCH |
Partial Update | Нет* | Частичное обновление ресурса — только указанные поля. |
DELETE |
Delete | Да | Удаление ресурса. После первого удаления повторный запрос имеет тот же эффект — ресурс уже удалён. |
Дополнительные методы
- HEAD — как GET, но сервер возвращает только заголовки, без тела. Полезно для получения метаданных без загрузки контента.
- OPTIONS — возвращает список поддерживаемых методов для ресурса. Используется, в том числе, для CORS preflight-запросов.
3. API и RESTful
Что такое API
API (Application Programming Interface) — инструкция для программ, описывающая, как они могут взаимодействовать друг с другом. Аналогия: официант в ресторане — принимает заказ у клиента и передаёт его на кухню; стороны не взаимодействуют напрямую.
API vs Веб-приложение
| API | Веб-приложение |
|---|---|
| Интерфейс взаимодействия между программами | ПО для выполнения задач через браузер |
| Предоставляет методы и точки входа для других программ | Состоит из фронтенда (браузер) и бэкенда (сервер) |
| Может использоваться несколькими приложениями одновременно | Может использовать API для внешних сервисов |
Пример: Google Maps API используется приложениями для доставки еды, заказа такси и навигации — три разных приложения, один API.
RESTful архитектура
REST (Representational State Transfer) — архитектурный стиль для API, использующий принципы HTTP. Данные представлены как ресурсы, доступные по URL.
Принципы REST
- Клиент-сервер: разделение позволяет развивать части независимо.
- Без сохранения состояния (stateless): каждый запрос содержит всю необходимую информацию; сервер не запоминает предыдущие запросы.
- Кэшируемость: ответы могут кэшироваться, что ускоряет загрузку.
- Единообразие интерфейса: ресурсы доступны через стандартные методы.
- Слой системы: система может состоять из нескольких уровней (прокси, балансировщик).
4. Конфигурация Flask-приложения
Flask-приложения используют классы конфигурации для раздельного управления настройками в разных средах: разработка, тестирование, продакшн.
Конфигурационный файл
# config.py
class Config:
DEBUG = False
TESTING = False
SQLALCHEMY_DATABASE_URI = 'sqlite:///community_pulse.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
class ProductionConfig(Config):
pass # использует переменные окружения
Загрузка конфигурации из окружения
import os
config_name = os.environ.get('FLASK_ENV', 'development')
config_class = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
}.get(config_name, DevelopmentConfig)
app.config.from_object(config_class)
FLASK_ENV в Flask 3.x используйте переменную FLASK_DEBUG=1 или кастомную переменную APP_ENV. Переменная FLASK_ENV устарела в Flask 2.3+.
⚠️ Проверить по документации Flask 3.x
5. Роутинг в Flask
Простой маршрут
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Добро пожаловать в Community Pulse!"
Маршрут с переменными
Переменные указываются в угловых скобках: <тип:имя>.
@app.route('/questions/<int:question_id>')
def show_question(question_id):
return f"Вопрос с ID {question_id}"
Конвертеры типов
| Конвертер | Что принимает |
|---|---|
string | Любой текст без слэшей (по умолчанию) |
int | Целые числа |
float | Числа с плавающей точкой |
path | Строки, включая слэши (файловые пути) |
uuid | Строки в формате UUID |
HTTP-методы в маршруте
@app.route('/questions', methods=['GET', 'POST'])
def questions():
if request.method == 'GET':
# вернуть список вопросов
pass
elif request.method == 'POST':
# создать новый вопрос
pass
6. Blueprints — модульная организация
Для крупных проектов Flask-приложение делится на модули — Blueprints. Каждый Blueprint отвечает за свою часть функциональности и может разрабатываться независимо.
Создание Blueprint
# app/routers/questions.py
from flask import Blueprint, jsonify, request
questions_bp = Blueprint('questions', __name__)
@questions_bp.route('/')
def list_questions():
return jsonify({"questions": []})
@questions_bp.route('/', methods=['POST'])
def add_question():
data = request.get_json()
return jsonify({"created": data}), 201
Регистрация Blueprint с url_prefix
# app/__init__.py
from flask import Flask
from app.routers.questions import questions_bp
from app.routers.responses import responses_bp
def create_app():
app = Flask(__name__)
app.register_blueprint(questions_bp, url_prefix='/questions')
app.register_blueprint(responses_bp, url_prefix='/responses')
return app
Результат: GET /questions/ вызывает list_questions, POST /questions/ вызывает add_question.
Преимущества Blueprints
- Модульность: каждый Blueprint разрабатывается и тестируется независимо.
- Масштабируемость: большое приложение легко разделить на компоненты.
- Повторное использование: Blueprint можно подключить к нескольким приложениям.
7. Application Factory Pattern
Вместо создания объекта app на уровне модуля — использование фабричной функции create_app(). Это современная практика для масштабируемых Flask-приложений.
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy() # расширение создаётся БЕЗ привязки к app
def create_app(config_name='development'):
app = Flask(__name__)
# загрузка конфигурации
from config import config_map
app.config.from_object(config_map[config_name])
# инициализация расширений
db.init_app(app) # привязка к конкретному app
# регистрация blueprints
from app.routers.questions import questions_bp
from app.routers.responses import responses_bp
app.register_blueprint(questions_bp, url_prefix='/questions')
app.register_blueprint(responses_bp, url_prefix='/responses')
return app
# run.py
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run()
8. Структура проекта Community Pulse
/community_pulse/
|-- app/
| |-- __init__.py # create_app(), инициализация db
| |-- routers/
| | |-- __init__.py
| | |-- questions.py # Blueprint для /questions
| | |-- responses.py # Blueprint для /responses
| |-- models/
| | |-- __init__.py
| | |-- questions.py # Модель Question
| | |-- responses.py # Модель Response
| |-- schemas/
| |-- __init__.py
| |-- question.py # Pydantic-схемы для Question
| |-- response.py # Pydantic-схемы для Response
|-- config.py # классы конфигурации
|-- run.py # точка входа
Структура маршрутов
| URL | Метод | Описание |
|---|---|---|
/questions | GET | Список всех вопросов |
/questions | POST | Создать новый вопрос |
/questions/<id> | GET | Получить вопрос по ID |
/questions/<id> | PUT | Обновить вопрос |
/questions/<id> | DELETE | Удалить вопрос |
/responses | GET | Статистика ответов |
/responses | POST | Добавить ответ |