Какие уровни API для работы с базой данных предоставляет SQLAlchemy?

Ответ

SQLAlchemy поддерживает два основных уровня взаимодействия с базой данных:

  1. Core – низкоуровневый API, максимально приближенный к SQL. Он позволяет работать напрямую с таблицами, соединениями и SQL-выражениями. Используется, когда требуется полный контроль над генерируемым SQL или для высокопроизводительных операций.

    Пример Core API:

    from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData
    
    engine = create_engine('sqlite:///example.db')
    metadata = MetaData()
    users_table = Table('users', metadata,
        Column('id', Integer, primary_key=True),
        Column('name', String),
    )
    metadata.create_all(engine)
    # Дальнейшие операции с users_table через engine
  2. ORM (Object Relational Mapper) – высокоуровневый API, который отображает таблицы базы данных на Python-классы (модели). Это упрощает работу с данными, позволяя оперировать объектами вместо SQL-запросов, что повышает продуктивность и читаемость кода.

    Пример ORM API:

    from sqlalchemy import create_engine, Column, Integer, String
    from sqlalchemy.orm import declarative_base, sessionmaker
    
    engine = create_engine('sqlite:///example.db') # Создаем движок для ORM
    Base = declarative_base()
    
    class User(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True)
        name = Column(String)
    
    Base.metadata.create_all(engine) # Создаем таблицы, если их нет
    
    Session = sessionmaker(bind=engine)
    session = Session()
    
    user = User(name='Alice')
    session.add(user)
    session.commit()

Основные различия и когда что использовать:

  • Core предоставляет максимальную гибкость и производительность, идеально подходит для сложных, оптимизированных запросов или работы с существующими схемами.
  • ORM значительно упрощает разработку бизнес-логики, абстрагируя детали работы с БД. Предпочтителен для большинства CRUD-операций и когда важна скорость разработки.
  • ORM использует Core "под капотом" для выполнения SQL-запросов.

Ответ 18+ 🔞

Давай разберём эту вашу SQLAlchemy, чтобы наконец понять, где тут Core, а где ORM, а то голова уже пухнет, как у того Герасима, когда он Муму топил.

Смотри, есть два пути, как с базой общаться, прям как в жизни: можно грубо и по-деловому, а можно с нежностью и обёрточками.

Первый путь — Core. Это как взять голый SQL и натянуть на него питоновские трусы. Низкоуровнево, мощно, контролируешь каждый чих. Если ты перфекционист-задрот, которому важно, чтобы каждый запрос был выточен, как яйцо Фаберже — тебе сюда.

from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData

engine = create_engine('sqlite:///example.db')
metadata = MetaData()
users_table = Table('users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String),
)
metadata.create_all(engine)
# Дальнейшие операции с users_table через engine

Видишь? Никаких намёков на объекты. Чистые таблицы, колонки, метаданные. Прям как на стройке — кирпичи, бетон, руки в пыли. Зато если накосячишь — сам и виноват, блядь.

Второй путь — ORM. А это уже высший пилотаж, для ленивых гениев. Берёшь свои питоновские классы, размазываешь по ним волшебный крем declarative_base(), и они волшебным образом становятся таблицами в базе. Красота, ёпта!

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

engine = create_engine('sqlite:///example.db') # Создаем движок для ORM
Base = declarative_base()

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

Base.metadata.create_all(engine) # Создаем таблицы, если их нет

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

user = User(name='Alice')
session.add(user)
session.commit()

Смотри, какая магия! Создал объект user, как будто обычный класс, плюнул его в session.add() — и он уже в базе! Ни одного прямого SQL-запроса не увидел. ORM сам всё причешет и отправит, будто услужливый дворецкий.

Так когда что брать, чтобы не облажаться?

  • Core — это когда тебе надо, блядь. Сложные аналитические запросы, тонкая настройка производительности, или работа с легаси-схемой, которая выглядит так, будто её проектировал пьяный ёжик. Полный контроль, но и полная ответственность.
  • ORM — это для хочу. Быстро накодить бизнес-логику, не забивая голову синтаксисом JOIN'ов. CRUD-операции плодятся как кролики. Разработка летит, код читается легко. Но иногда ORM может сгенерить такой монструозный запрос, что база сдохнет от удивления. За абстракцию платим, сука, производительностью.

И главное — они не воюют! ORM внутри себя использует Core, как скелет. Это как машина: можно рулить на автомате (ORM), а можно воткнуть механику (Core) и почувствовать каждую кочку на дороге.

Выбирай по ситуации. Хочешь быстро и с комфортом — ORM. Хочешь всё делать сам и знать каждую косточку — Core. А можно и миксовать, главное — не начать материться на неправильный выбор посреди ночного дебага.