Сначала измерьте

ORM скрывает SQL, поэтому страница может слать сотни запросов без видимых признаков. Цикл профилирования всегда один: измерить, исправить, закрепить результат тестом.

Цикл профилирования
Цикл профилирования
ИнструментНа что отвечаетГде
Debug Toolbarсколько запросов шлёт эта страницаразработка
assertNumQueriesне вырос ли счёт сноватесты, CI
nplusoneгде сейчас N+1разработка
silkкакие запросы и функции медленныеstaging, API
explain()как база выполняет запросshell, любой этап

Подключение Debug Toolbar

Установите pip install django-debug-toolbar. Всё добавляйте только при DEBUG:

python
# settings.py
if DEBUG:
    INSTALLED_APPS += ["debug_toolbar"]
    MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware")
    INTERNAL_IPS = ["127.0.0.1"]
python
# urls.py
from django.conf import settings
from django.urls import include, path

urlpatterns = [
    # ...
]

if settings.DEBUG:
    urlpatterns += [path("__debug__/", include("debug_toolbar.urls"))]

⚠️ При пустом INTERNAL_IPS панель скрыта. В Docker добавьте IP шлюза контейнера или используйте SHOW_TOOLBAR_CALLBACK в DEBUG_TOOLBAR_CONFIG. Ещё нужен django.contrib.staticfiles.

ПанельЧто показывает
SQLзапросы, время, дубли, кнопка EXPLAIN
TimeCPU и общее время
Templatesотрисованные шаблоны и контекст
Historyпрошлые запросы, включая AJAX
Profilingфункции через cProfile (по умолчанию выключена)