✅ Решения: SQLAlchemy — движок, сессия, наполнение БД

⚡ Ключевые паттерны из решений

  • Движок в памяти: create_engine('sqlite:///:memory:')
  • Сессия как контекстный менеджер: with Session(engine) as session:
  • Всегда объявляй __tablename__ в модели
  • Создавать таблицы до открытия сессии: Base.metadata.create_all(engine)
  • После commit() — объект получает id из БД

Решение задачи 1 (из лекции): Создание движка

Логика: create_engine принимает строку подключения. Для SQLite в памяти — специальный адрес sqlite:///:memory:. Данные существуют только пока работает программа.

from sqlalchemy import create_engine

# Задача 1: движок для подключения к SQLite в памяти
# "sqlite:///:memory:" — три слеша, затем :memory:
engine = create_engine('sqlite:///:memory:')

print('Движок создан:', engine)

Решение задачи 2 (из лекции): Создание сессии

Логика: сессия — рабочий интерфейс между объектами и БД. Контекстный менеджер with Session(engine) as session: гарантирует закрытие сессии при выходе из блока.

from sqlalchemy import create_engine
from sqlalchemy.orm import Session

# Движок из задачи 1
engine = create_engine('sqlite:///:memory:')

# Задача 2: создать сессию
with Session(engine) as session:
    print('Сессия открыта')
    # Здесь выполняется работа с объектами
# Сессия закрывается автоматически — объекты переходят в Detached
Стиль лекции (1.x): в лекции сессия создаётся через sessionmaker(bind=engine) и Session(). Контекстный менеджер — современный эквивалент 2.x. Оба подхода — в «Старый vs Новый».

Решение задачи 3: Модель User и добавление данных

Логика: полный цикл — объявить модель, создать таблицу, открыть сессию, добавить объект, зафиксировать. После commit() SQLAlchemy заполняет id значением из БД.

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

# Шаг 1: движок (задача 1)
engine = create_engine('sqlite:///:memory:')

# Шаг 2: базовый класс для всех моделей
class Base(DeclarativeBase):
    pass

# Шаг 3: модель User — точно как в примере лекции (стиль 2.x)
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)

# Шаг 4: создать таблицу в БД
# SQLAlchemy анализирует все подклассы Base и создаёт для них таблицы
Base.metadata.create_all(engine)

# Шаг 5: сессия (задача 2) + добавление объекта
with Session(engine) as session:
    # Создание нового пользователя — состояние Transient
    new_user = User(name='John Doe', age=30)

    # Добавить в сессию — состояние Pending
    session.add(new_user)

    # Зафиксировать в БД — состояние Persistent
    # После commit() SQLAlchemy заполняет id из БД
    session.commit()

    print(f'Добавлен пользователь: id={new_user.id}, name={new_user.name}, age={new_user.age}')
    # Вывод: Добавлен пользователь: id=1, name=John Doe, age=30

Решение задачи 4: Логирование SQL-запросов

Логика: логгер sqlalchemy.engine получает все SQL-запросы, генерируемые движком. Уровень INFO включает вывод запросов CREATE TABLE, INSERT, SELECT.

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()

# В консоли будет видно:
# INFO:sqlalchemy.engine.Engine:BEGIN (implicit)
# INFO:sqlalchemy.engine.Engine:CREATE TABLE users (...)
# INFO:sqlalchemy.engine.Engine:INSERT INTO users (name, age) VALUES (?, ?)
# INFO:sqlalchemy.engine.Engine:[generated in ...] ('John Doe', 30)
# INFO:sqlalchemy.engine.Engine:COMMIT