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

«Как отследить SQL-запросы, выполняемые в Django» — вопрос из категории Django, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Отслеживание 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']}")

    # ...