💻 Примеры: SQLAlchemy — движок, сессия, наполнение БД

⚡ Минимальный рабочий пример (как в лекции, стиль 2.x)

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

engine = create_engine('sqlite:///:memory:')

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()
    print(f'Добавлен пользователь id={new_user.id}')

Пример 1: Модель User из лекции (стиль 2.x)

Это пример из лекции, адаптированный на современный API SQLAlchemy 2.x. Модель User с полями id, name, age — именно такую создаёт лекция.

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

# Движок: подключение к SQLite базе данных в памяти
engine = create_engine('sqlite:///:memory:')

# Базовый класс — от него наследуют все модели
class Base(DeclarativeBase):
    pass

# Модель User = таблица 'users' в БД
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)

# Для того чтобы в базе данных появилась таблица,
# вызываем create_all() — SQLAlchemy создаёт таблицы по описанным моделям
Base.metadata.create_all(engine)

# Создание нового пользователя и добавление в БД
with Session(engine) as session:
    new_user = User(name='John Doe', age=30)
    # Добавляем объект в сессию
    session.add(new_user)
    # Фиксируем изменения в базе данных
    session.commit()
    print(f'Добавлен пользователь: id={new_user.id}, name={new_user.name}')
Пояснение: пример из лекции использует declarative_base() и Column (SQLAlchemy 1.x). Здесь тот же пример на 2.x: DeclarativeBase, Mapped, mapped_column. Сравнение стилей — в «Старый vs Новый».

Пример 2: Движок SQLite в памяти + несколько пользователей

Практическая задача из лекции — создать движок к SQLite в памяти и сессию:

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

# Задача 1 из лекции: движок для SQLite в памяти
engine = create_engine('sqlite:///:memory:')

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)

# Задача 2 из лекции: создать сессию
with Session(engine) as session:
    # Добавляем нескольких пользователей
    users = [
        User(name='Alice', age=25),
        User(name='Bob', age=32),
        User(name='Charlie', age=28),
    ]
    session.add_all(users)
    session.commit()

    print(f'Добавлено пользователей: {len(users)}')
    for u in users:
        print(f'  id={u.id}, name={u.name}, age={u.age}')

Пример 3: Логирование SQL-запросов

Настройка логирования через модуль logging — из лекции:

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

# Настройка логирования (из лекции)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('sqlalchemy.engine')
logger.setLevel(logging.INFO)

engine = create_engine('sqlite:///:memory:')

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()
    # В консоли будет видно SQL:
    # INFO sqlalchemy.engine.Engine BEGIN (implicit)
    # INFO sqlalchemy.engine.Engine INSERT INTO users ...
Альтернатива: можно включить логирование прямо в движке через параметр echo=True:
engine = create_engine('sqlite:///:memory:', echo=True)
Это выводит все SQL-запросы в консоль без настройки модуля logging.

Пример 4: Состояния объекта в сессии

Демонстрация жизненного цикла объекта через состояния из лекции:

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

engine = create_engine('sqlite:///:memory:')

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)

# Создаём объект — состояние Transient (не связан с сессией)
user = User(name='Anna', age=22)
print(inspect(user).transient)   # True

with Session(engine) as session:
    # Добавляем в сессию — состояние Pending
    session.add(user)
    print(inspect(user).pending)  # True

    # После commit — состояние Persistent
    session.commit()
    print(inspect(user).persistent)  # True

# После закрытия сессии — состояние Detached
# Объект остаётся в памяти, но отсоединён от БД
print(inspect(user).detached)    # True