Как устроены запросы к базе данных в Django: через ORM или чистый SQL
Что проверяют
Умеете ли вы пользоваться ORM осознанно и знаете ли, когда спускаться к SQL.
Как отвечать
По умолчанию через ORM: Model.objects.filter(...) строит QuerySet, который ленив. Запрос уходит в базу не при создании, а при первом обращении к данным: перебор, list(), срез, len(), bool(). Поэтому фильтры можно накапливать, не касаясь базы.
Что даёт ORM: миграции, экранирование параметров, связи, единая модель. Что скрывает: реальный SQL, из-за чего легко получить проблему N+1.
Инструменты, которые стоит назвать:
select_relatedдля связей «к одному» (делает JOIN) иprefetch_relatedдля «ко многим» (отдельный запрос плюс склейка в Python);onlyиdeferдля сокращения набора колонок;annotateиaggregateдля вычислений на стороне базы;FиQ:Fделает атомарное обновление без гонки (F("views") + 1),Qсобирает сложные условия;bulk_createиbulk_updateвместо цикла с сохранением;iterator()для больших выборок, чтобы не тянуть всё в память.
Когда переходят на SQL: сложная аналитика с оконными функциями, специфика PostgreSQL (jsonb, полнотекстовый поиск, ON CONFLICT), тяжёлые пакетные операции. Инструменты: .raw(), RawSQL, connection.cursor(), а также .extra(), который устарел.
Как проверять: str(queryset.query) показывает SQL, django-debug-toolbar показывает число запросов, assertNumQueries в тестах защищает от возврата N+1.
Где спотыкаются
Обращаются к связям в цикле шаблона и получают сотни запросов.
Читают значение, прибавляют в Python и сохраняют, теряя обновления при конкуренции, вместо F().
Загружают полные объекты там, где нужны два поля.
Никогда не смотрят на сгенерированный SQL.