⚖️ Старый vs Новый: SQLAlchemy 1.x (лекция) и 2.x

🎯 Лекция написана на 1.x — здесь показан переход на современный 2.x

⚡ Кратко

  • Лекция (1.x): declarative_base(), Column(Integer, ...), sessionmaker(bind=engine)
  • Современно (2.x): class Base(DeclarativeBase), Mapped[int] = mapped_column(...), with Session(engine) as session:
  • Главное преимущество 2.x: статические аннотации типов — IDE знает типы полей, ошибки видны до запуска.
  • В интернете много кода на 1.x — при копировании проверяйте версию.
⚠️ Внимание: код в левой колонке — это синтаксис лекции (SQLAlchemy 1.x). Именно так написан учебный материал. Правая колонка показывает тот же код на современном API 2.x. В реальных проектах используйте 2.x.

1. Базовый класс

🔥 Как в лекции (SQLAlchemy 1.x)

# Из лекции — устаревший синтаксис
from sqlalchemy.orm import sessionmaker, declarative_base

Base = declarative_base()  # функция, не наследование

✨ Современно (SQLAlchemy 2.x)

# Современный синтаксис
from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
    pass  # наследование от класса

2. Объявление полей модели

🔥 Как в лекции (SQLAlchemy 1.x)

# Модель User из лекции (1.x)
from sqlalchemy import Column, Integer, String

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)   # без аннотаций
    name = Column(String(30))
    age = Column(Integer)
  • ❌ Нет аннотаций типов — IDE не знает, что user.name это строка
  • ❌ Mypy/pyright не проверяют типы полей

✨ Современно (SQLAlchemy 2.x)

# Та же модель User на 2.x
from sqlalchemy import String, Integer
from sqlalchemy.orm import Mapped, mapped_column

class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(30))
    age: Mapped[int] = mapped_column(Integer)
  • ✅ Аннотации типов — IDE знает точный тип каждого поля
  • ✅ Работает с Mypy, Pyright, Pylance
  • Mapped[тип | None] явно показывает необязательные поля

3. Создание сессии

🔥 Как в лекции (SQLAlchemy 1.x)

# Из лекции: sessionmaker + ручное создание экземпляра
from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)   # bind= устарело
session = Session()

session.add(new_user)
session.commit()
session.close()   # нужно закрывать вручную!

✨ Современно (SQLAlchemy 2.x)

# Контекстный менеджер — закрытие автоматическое
from sqlalchemy.orm import Session

with Session(engine) as session:
    session.add(new_user)
    session.commit()
# Сессия закрывается автоматически при выходе из with-блока

4. Полный пример (лекция 1.x → современный 2.x)

🔥 Полный код из лекции (1.x)

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base

Base = declarative_base()
engine = create_engine('sqlite:///example.db')

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    age = Column(Integer)

Session = sessionmaker(bind=engine)
session = Session()

Base.metadata.create_all(engine)

new_user = User(name='John Doe', age=30)
session.add(new_user)
session.commit()

✨ Тот же код на SQLAlchemy 2.x

from sqlalchemy import create_engine, String, Integer
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session

engine = create_engine('sqlite:///example.db')

class Base(DeclarativeBase):
    pass

class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(30))
    age: Mapped[int] = mapped_column(Integer)

Base.metadata.create_all(engine)

with Session(engine) as session:
    new_user = User(name='John Doe', age=30)
    session.add(new_user)
    session.commit()

Таблица отличий

Возможность SQLAlchemy 1.x (как в лекции) SQLAlchemy 2.x (актуально)
Базовый класс declarative_base() class Base(DeclarativeBase)
Поля модели Column(Integer, ...) Mapped[int] = mapped_column(...)
Создание сессии sessionmaker(bind=engine) + Session() with Session(engine) as session:
Импорт базы from sqlalchemy.orm import declarative_base from sqlalchemy.orm import DeclarativeBase
Типизация полей Нет статических аннотаций Полная поддержка Mapped[тип]
Закрытие сессии Вручную: session.close() Автоматически через контекстный менеджер
Важно: в интернете огромное количество примеров написано на SQLAlchemy 1.x. Если вы видите declarative_base() или sessionmaker(bind=engine) — это старая версия. В нашем курсе основные файлы (examples, tasks, solutions, homework) используют SQLAlchemy 2.x.