В чем ключевые различия между SQLAlchemy 1.4 и 2.0

Ответ

Ключевое различие заключается в том, что SQLAlchemy 2.0 вводит новый, полностью типизированный и унифицированный API (т.н. "2.0 style"), который стал стандартом. Версия 1.4 была переходной и поддерживала оба стиля (старый 1.x и новый 2.0) для обратной совместимости.

Основные отличия SQLAlchemy 2.0:

  1. Унифицированный Core API: Метод session.query() был заменен на select(), что унифицирует работу с Core и ORM.
  2. Полная поддержка типизации: Введены Mapped и mapped_column для явного объявления колонок модели, что обеспечивает полную поддержку статических анализаторов, таких как Mypy.
  3. Нативная поддержка asyncio: API для асинхронной работы был полностью переработан и стал более стабильным и интуитивным.

Сравнение синтаксиса:

  • Стиль 1.4 (и ранее):

    from sqlalchemy import Column, Integer, String
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    class User(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True)
        name = Column(String(50))
    
    # Запрос
    # users = session.query(User).filter_by(name='John').all()
  • Стиль 2.0 (рекомендуемый):

    from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
    
    class Base(DeclarativeBase):
        pass
    
    class User(Base):
        __tablename__ = 'users'
        id: Mapped[int] = mapped_column(primary_key=True)
        name: Mapped[str] = mapped_column(String(50))
    
    # Запрос
    # from sqlalchemy import select
    # statement = select(User).where(User.name == 'John')
    # users = session.scalars(statement).all()

Рекомендация: Для всех новых проектов следует использовать исключительно синтаксис SQLAlchemy 2.0.

Ответ 18+ 🔞

Да ты посмотри, какая хуйня творится! SQLAlchemy, блядь, выпустили версию 2.0, и там, сука, всё перевернули с ног на голову, но как бы по-хорошему. А версия 1.4 — это такой хитрожопый переходный мостик, где и старое работало, и новое уже можно было тыкать.

В чём, блядь, соль-то?

  1. API новый, универсальный. Раньше ты в ORM session.query(User) писал, а в Core select(). Теперь, ёпта, везде select()! Красота, блядь, единообразие.
  2. Типизация наше всё. Раньше колонки объявляли просто Column(), а теперь надо Mapped и mapped_column писать. Зато твой Mypy не будет орать как резаный, всё проверит. Не "подозрение ебать чувствую", а уверенность, что код не развалится.
  3. Асинхронность не кривая. В 2.0 asyncio поддержали по-взрослому, не то что раньше, где всё было через жопу и костыли.

Смотри, как раньше было и как теперь:

  • Старый стиль (1.4 и древнее):

    from sqlalchemy import Column, Integer, String
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    class User(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True)
        name = Column(String(50))
    
    # Запрос
    # users = session.query(User).filter_by(name='John').all()

    Скучно, предсказуемо, типов никаких.

  • Новый стиль 2.0 (охуенный):

    from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
    
    class Base(DeclarativeBase):
        pass
    
    class User(Base):
        __tablename__ = 'users'
        id: Mapped[int] = mapped_column(primary_key=True)
        name: Mapped[str] = mapped_column(String(50))
    
    # Запрос
    # from sqlalchemy import select
    # statement = select(User).where(User.name == 'John')
    # users = session.scalars(statement).all()

    Красота, блядь! Всё явно, типы на месте, код читается как книга. Ну, как книга про Герасима и Муму, только с хэппи-эндом.

Итог, ёпта: Если новый проект затеваешь — даже не думай, блядь, бери сразу синтаксис SQLAlchemy 2.0. Не будь тем самым Герасимом, который топиит свою же собаку, используя устаревший API. Иди в ногу со временем, в рот меня чих-пых!