✅ Ответы на вопросы самопроверки
Блок 1. SQLAlchemy — основы
Зачем нужна SQLAlchemy?
SQLAlchemy — библиотека Python для работы с реляционными БД через SQL и объектно-ориентированный подход. Даёт два уровня: ORM (работа через Python-классы/объекты) и Core (SQL-выражения через Python API). Избавляет от написания «сырого» SQL для типовых операций, обеспечивает портируемость между СУБД.
Основные принципы ORM
- Отображение объектов — таблицы БД отображаются на Python-классы.
- Абстрагирование от SQL — работа с данными без написания SQL-запросов.
- Отображение связей — связи между таблицами представлены как связи между объектами.
- Поддержка различных СУБД — абстракция над конкретной базой данных.
Core vs ORM
| Преимущества | Недостатки | |
|---|---|---|
| ORM | Абстракция, лёгкость, гибкость, интеграция | Производительность, сложность при нестандартных запросах |
| Core | Производительность, полный контроль | Сложнее писать, больше кода |
Когда что: для сложной логики и высокой производительности — Core; для скорости разработки и типовых CRUD — ORM.
Строка подключения
'<DBMS>+<library>://<user>:<password>@<host>:<port>/<database>'
Компоненты: DBMS (тип СУБД), library (драйвер), user/password (учётные данные), host:port (адрес сервера), database (имя базы).
Сессия и её жизненный цикл
Сессия — рабочий интерфейс между объектами Python и БД. Управляет транзакциями и отслеживает изменения.
Жизненный цикл: создание экземпляра Session → работа с объектами (add/delete) → commit() для фиксации → close() для закрытия.
После закрытия сессии: ответ C
Объекты остаются в памяти Python, но переходят в состояние Detached — отсоединены от базы данных. Обращение к «ленивым» атрибутам вызовет исключение DetachedInstanceError.
Блок 2. Модели и связи
Роль __tablename__: ответ C
__tablename__ указывает имя таблицы в базе данных, которую будет представлять данная модель.
Параметр nullable
nullable=False означает, что колонка не может принимать значение NULL. При попытке вставить NULL SQLAlchemy (или сама СУБД) выбросит ошибку.
nullable=True (по умолчанию) — NULL допустим.
Функция relationship() — 3 параметра
relationship() определяет связь между ORM-моделями на уровне Python. Примеры параметров:
back_populates— двунаправленная связь (явная).lazy— стратегия загрузки: select/joined/subquery/noload.cascade— каскадные операции (напр."all, delete-orphan").uselist=False— связь 1:1.
Связь M:N
Для связи «многие-ко-многим» необходимо создать ассоциативную таблицу с двумя внешними ключами, ссылающимися на первичные ключи обеих связанных таблиц. В relationship() передаётся параметр secondary=ассоциативная_таблица.
Блок 3. Запросы
CRUD — правильные пары
- 1 (Create) → C (Добавление новых записей)
- 2 (Read) → D (Доступ к данным)
- 3 (Update) → A (Изменение существующих данных)
- 4 (Delete) → B (Удаление данных)
Ответ B — .one()
.one() возвращает ровно один объект. Если объектов 0 — NoResultFound. Если 2 и более — MultipleResultsFound.
Утверждение ЛОЖНО
.first() возвращает первый объект или None, если результат пуст. Он никогда не выбрасывает исключение.
having() vs filter()
filter() применяется к исходным данным (WHERE в SQL) — до группировки.
having() применяется к результатам агрегатных функций — после group_by(). Нельзя использовать вместо filter().
Утверждение ЛОЖНО
order_by() может принимать несколько критериев: .order_by(desc(User.age), User.name).
scalar()
Извлекает первый столбец первой строки из результата запроса. Возвращает None, если результат пуст. Используется с агрегатными функциями: session.query(func.count(User.id)).scalar().
aliased()
aliased() создаёт псевдоним для модели. Необходима при Self Join — когда одна и та же таблица соединяется сама с собой. Позволяет различать два «экземпляра» одной таблицы в одном запросе.
from sqlalchemy.orm import aliased
addr1 = aliased(Address)
addr2 = aliased(Address)
session.query(addr1.user_id, addr2.user_id).join(
addr2, addr1.description == addr2.description
).filter(addr1.user_id != addr2.user_id).all()