Как отследить SQL-запросы, выполняемые в Django

Ответ

Отслеживание SQL-запросов в Django — ключевая задача для оптимизации производительности. Вот основные подходы, отладочные и программные.

1. Django Debug Toolbar (для разработки)

Это самый популярный и наглядный способ. django-debug-toolbar встраивает в страницу панель с детальной информацией о запросе, включая все выполненные SQL-запросы, их количество и время выполнения.

Установка и настройка в settings.py:

# pip install django-debug-toolbar

INSTALLED_APPS = [
    # ...
    'debug_toolbar',
]

MIDDLEWARE = [
    # ...
    'debug_toolbar.middleware.DebugToolbarMiddleware',
]

# IP-адреса, с которых будет видна панель
INTERNAL_IPS = [
    '127.0.0.1',
]

2. Логирование в консоль

Django может выводить все SQL-запросы в консоль через стандартный механизм логирования. Это полезно при выполнении management-команд или в окружениях, где нельзя использовать Debug Toolbar.

Настройка в settings.py:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'level': 'DEBUG',
        },
    },
}

3. Программный доступ через connection.queries

В режиме DEBUG = True Django сохраняет все запросы в списке django.db.connection.queries. Это позволяет анализировать их программно, например, в тестах или кастомном middleware для сбора метрик.

Пример в views.py или тестах:

from django.db import connection
from django.conf import settings

def my_view(request):
    # ... ваш код, выполняющий запросы к БД ...

    if settings.DEBUG:
        query_count = len(connection.queries)
        print(f"Выполнено запросов: {query_count}")
        for query in connection.queries:
            print(f"[{query['time']}с] {query['sql']}")

    # ...

Ответ 18+ 🔞

Ах ты ж, разработчик, подойди сюда, я тебе сейчас такую штуку расскажу про SQL-запросы в Django, что ты обоссаешься со смеху! Ну, точнее, не со смеху, а с удивления, пиздец, насколько всё просто, если знать, куда смотреть. Сидишь ты, значит, на проекте, а он тормозит, как черепаха в сиропе, и ты думаешь: «Ну что за хуйня, блядь? Кто тут столько запросов навешал?». А оказывается, это ты сам, распиздяй, в цикле ORM-запросы гоняешь! Ну ладно, слушай сюда, как это дело отслеживать.

1. Django Debug Toolbar — твой лучший друг в разработке, ёпта!

Это такая панелька, которая прилипает к правому краю браузера и показывает тебе всю подноготную. Сколько запросов, какие именно, сколько времени каждый жрал — всё, как на духу. Установить — раз плюнуть.

# pip install django-debug-toolbar, блядь, не забудь!

INSTALLED_APPS = [
    # ... остальные приложения ...
    'debug_toolbar',  # воткнул и забыл
]

MIDDLEWARE = [
    # ... другое middleware ...
    'debug_toolbar.middleware.DebugToolbarMiddleware',  # вот это вот важно, сука, не перепутай порядок!
]

# А это чтобы панель только у тебя светилась, а не у всех пользователей, а то они охуеют
INTERNAL_IPS = [
    '127.0.0.1',
]

Вот, поставил, запустил сервер — и видишь на каждой странице эту панель. Нажал на SQL — и тебе вываливается список всех запросов. А если какой-то запрос повторяется, как мантра, сто пятьсот раз — сразу видно, где ты, мудак, накосячил с N+1 проблемой. Просто красота, в рот меня чих-пых!

2. Логирование в консоль — для тех, кто любит по-старинке

А бывает, что Debug Toolbar не встаёт — например, в API или когда команды management-ские гоняешь. Ну или просто неохота в браузер тыкать. Тогда можно настроить логирование, чтобы все SQL-запросы летели прямо в консоль, как из пулемёта.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {  # Вот этот логгер, блядь, ключевой!
            'handlers': ['console'],
            'level': 'DEBUG',  # Выставляем DEBUG, чтобы все запросы показывал
        },
    },
}

Добавил это в settings.py — и всё, теперь при каждом запросе в консоль сыпется куча строк с SQL. Увидишь там что-нибудь вроде SELECT * FROM auth_user WHERE id = 1 — и сразу поймёшь, кто виноват. Главное — не охуеть от количества, если накосячил.

3. Программный доступ — для крутых перцев, которые хотят всё контролировать

А вот это уже для тех, кто любит ковыряться в кишках. В режиме DEBUG = True Django копит все запросы в специальном списке django.db.connection.queries. Можешь достать их оттуда и сделать что хочешь — например, посчитать, сколько их там наворотилось, или в тестах проверять, не наделал ли ты лишнего.

from django.db import connection
from django.conf import settings

def my_view(request):
    # ... тут твой код, который наверняка делает кучу запросов ...

    if settings.DEBUG:  # На всякий случай проверяем, что мы в отладке, а то на проде ёбнемся
        query_count = len(connection.queries)
        print(f"Выполнено запросов: {query_count}")  # Овердохуища, Карл!
        for query in connection.queries:
            print(f"[{query['time']}с] {query['sql']}")  # Время и сам запрос — всё как есть

    # ...

Вот так, блядь, взял и вывел. Увидишь, что запросов, как говна за баней, — и сразу бежишь оптимизировать. Может, индексы добавить, а может, select_related или prefetch_related прикрутить. В общем, дело за тобой.

Короче, выбирай способ по душе. Лично я за Debug Toolbar, потому что он нагляден, как хуй в бане. Но если нужно что-то автоматизировать — бери логирование или connection.queries. Главное — не игнорируй эти инструменты, а то потом будешь сидеть и думать: «Ну почему же оно так медленно, ёпта?». А потому что сам виноват, распиздяй!