⚖️ Старый vs Новый: лекция (старое) → современное
В лекции ряд паттернов написан на устаревших API (Pydantic v1, SQLAlchemy 1.x Query API). Этот раздел показывает: как было в лекции → как правильно сегодня.
1. Pydantic: orm_mode → from_attributes (v1 → v2)
Из лекции (Pydantic v1 — устарело)
from pydantic import BaseModel
class QuestionResponse(BaseModel):
id: int
text: str
class Config:
orm_mode = True # Pydantic v1
from_attributes = True # дубль в лекции
# Использование
QuestionResponse.from_orm(question)
Современный код (Pydantic v2)
from pydantic import BaseModel, ConfigDict
class QuestionResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
text: str
# Использование
QuestionResponse.model_validate(question)
Ключевые изменения Pydantic v1 → v2:
| Pydantic v1 (лекция) | Pydantic v2 (актуально) |
|---|---|
class Config: orm_mode = True | model_config = ConfigDict(from_attributes=True) |
Schema.from_orm(obj) | Schema.model_validate(obj) |
schema.dict() | schema.model_dump() |
schema.json() | schema.model_dump_json() |
@validator('field') | @field_validator('field') |
2. SQLAlchemy: Query.get() → Session.get() (1.x → 2.x)
Из лекции (Query API 1.x — устарело)
# Поиск по первичному ключу
question = Question.query.get(id)
# Все записи
questions = Question.query.all()
# Фильтрация
stat = Statistic.query.filter_by(
question_id=qid
).first()
Современный код (SQLAlchemy 2.x)
# Поиск по первичному ключу
question = db.session.get(Question, id)
# Все записи
from sqlalchemy import select
questions = db.session.execute(
select(Question)
).scalars().all()
# Фильтрация
stat = db.session.execute(
select(Statistic).where(
Statistic.question_id == qid
)
).scalar_one_or_none()
Совместимость: Flask-SQLAlchemy 3.x сохраняет Model.query для обратной совместимости, но помечает его deprecated. В production-коде используйте db.session.execute(select(...)).
3. Инициализация приложения: прямая → Application Factory
Из лекции (простая инициализация)
# run.py — всё в одном файле
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import DevelopmentConfig
app = Flask(__name__)
app.config.from_object(DevelopmentConfig)
db = SQLAlchemy(app) # прямая привязка
Современный подход (Application Factory)
# app/__init__.py
def create_app(config=None):
app = Flask(__name__)
if config:
app.config.from_object(config)
db.init_app(app) # отложенная привязка
# ... регистрация blueprints
return app
# run.py
app = create_app(DevelopmentConfig)
Application Factory позволяет создавать несколько экземпляров приложения (например, тестовый и продуктовый) с разными конфигурациями.
4. Dataclass-контракты → Pydantic-схемы
Из лекции (dataclass)
from dataclasses import dataclass
from typing import Optional
@dataclass
class QuestionData:
text: str
@dataclass
class ErrorResponse:
error: str
@dataclass
class SuccessResponse:
message: str
id: Optional[int] = None
# Использование
data = QuestionData(**request.get_json())
return jsonify(SuccessResponse("OK", 1).__dict__)
Современный подход (Pydantic v2)
from pydantic import BaseModel, Field
class QuestionCreate(BaseModel):
text: str = Field(..., min_length=12)
class QuestionResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
text: str
# Использование
data = QuestionCreate(**request.get_json())
return jsonify(
QuestionResponse.model_validate(q).model_dump()
)
Pydantic автоматически валидирует данные, генерирует понятные ошибки и поддерживает сложные типы (Annotated, EmailStr, и т.д.).