Django 5 для начинающих

Прогресс по курсу:  9/1004

10.6 Оптимизация SQL запросов и установка Debug-Toolbar
3 из 4 шагов пройдено
0 из 5 баллов  получено

В этом разделе мы рассмотрим оптимизацию SQL запросов Django ORM с помощью select_related(), используя менеджер и Django Debug Toolbar. Так же будет показано решение проблем с запросами N+1 в Django.

Проблема n+1 (или проблема "жадной" загрузки) - это частое явление при использовании ORM, когда при попытке загрузить данные из связанных таблиц происходит множественный запрос к базе данных вместо одного оптимизированного запроса.

Для начала установим Django Debug Toolbar:

pip install django-debug-toolbar

Далее в файл настроек добавим следующий код:

INTERNAL_IPS = [
    '127.0.0.1', # New
]

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apps.blog.apps.BlogConfig',
    'mptt',
    'django_mptt_admin',
    'debug_toolbar', # приложение тулбара

]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',  # Middleware тулбара
]

Django Debug Toolbar отображается только в том случае, если в списке INTERNAL_IPS есть IP приложения. Для разработки на локальном компьютере мы добавляем в список IP 127.0.0.1.

В случае если появляются проблемы с отображением тулбара, то добавьте следующий код в файл настроек:

def show_toolbar(request):
    return True


DEBUG_TOOLBAR_CONFIG = {
    "SHOW_TOOLBAR_CALLBACK": show_toolbar,
}

Этот код отключит любые проверки отображения тулбара. Но используйте этот код только для тестирования при локальной разработке, если вы забудете и сделаете деплой проекта с ним, все ваши посетители также увидят вашу панель инструментов отладки.


Теперь необходимо изменить главный urls.py, добавив работу дебагера в режиме отладки DEBUG = True:

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += [path('__debug__/', include('debug_toolbar.urls'))]

Запустим сервер и проверим работу дебагера:

Мы видим что он прекрасно работает, перейдем в раздел SQL и посмотрим запросы:

На данном скриншоте мы можем заметить одинаковые запросы к пользователю, а также к категориям. Это проблема, и называется она N+1. Если бы на странице было бы ещё больше статей, то и запросов SQL было бы пропорционально больше.

В следующем шаге мы попробуем решить эту проблему.


  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий

Выделите, пожалуйста, блок кода: INTERNAL_IPS = [ '127.0.0.1', ] в листинге. Не сразу заметил, пришлось некоторое время поломать голову.

@Кирилл_Семенихин, Выделил в коде и добавил немного описания после кода.

Ребят этот тулбар работает коряво через INTERNAL_IPS = [ '127.0.0.1', ], если у вас есть какие-то проблемы с js на странице или тулбар не отображается вообще никак(как это было у меня), то замените INTERNAL_IPS = [ '127.0.0.1', ]  на 

def show_toolbar(request):
    return True


DEBUG_TOOLBAR_CONFIG = {
    "SHOW_TOOLBAR_CALLBACK": show_toolbar,
}

и всё должно заработать. Создатели курса добавьте эту часть кода в этот раздел, а то ребята не всегда в комменты лезут.

@Шамбер_Егор, спасибо, добавил.

Скажите, пожалуйста. Правильно ли я понял.

Об этом:

"На данном скриншоте мы можем заметить одинаковые запросы к пользователю, а также к категориям. "

говорит это:

"2 similar queries."

@Aleksandr_Gurov, да, и также в списке видим одинаковые запросы к таблице категорий и пользователей.

@Дмитрий_Селезнев,  спасибо