⚖️ Старый vs Новый: лекция (старое) → современное

🎯 Миграция на актуальные API К оглавлению урока

В лекции ряд паттернов написан на устаревших 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 = Truemodel_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, и т.д.).