Skip to content

Latest commit

 

History

History
338 lines (219 loc) · 11.1 KB

File metadata and controls

338 lines (219 loc) · 11.1 KB

Модуль 5. Урок 32. Оптимизация сайта с Django Debug Toolbar

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

Django Debug Toolbar — это инструмент, который позволяет увидеть сайт “изнутри”: время рендеринга, SQL-запросы, работу шаблонов, статических файлов, middleware и многое другое.

В этом уроке мы:

  • установим и настроим Debug Toolbar;
  • научимся работать с панелью SQL и искать проблемные запросы;
  • разберём реальные примеры оптимизации;
  • изучим select_related() и prefetch_related();
  • проверим результаты в браузере;
  • выполним практические задания.

1. Зачем разработчику нужна Django Debug Toolbar

Debug Toolbar — это панель разработчика, встроенная в Django-проект.

С её помощью можно:

Проверять SQL-запросы

  • количество запросов,
  • сами SQL-запросы,
  • время выполнения каждого,
  • повторяющиеся запросы.

Анализировать производительность

  • скорость формирования страницы,
  • влияние шаблонов,
  • время загрузки контента.

Слежение за настройками и HTTP-заголовками

Полезно при ошибках, связанных с middleware, cookie, CORS и т.д.

Поиск неоптимальных ORM-запросов

Например:

  • N+1 проблема, когда к каждому объекту Django дополнительно делает запросы (часто в шаблонах).
  • медленные JOIN-ы,
  • лишние SELECT’ы при работе с ForeignKey и ManyToMany.

2. Установка Django Debug Toolbar

Устанавливаем пакет:

pip install django-debug-toolbar

Теперь нужно подключить его в проекте.


3. Настройка проекта cinemahub

Откроем settings.py.

3.1 Добавляем приложение

INSTALLED_APPS += [
    'debug_toolbar',
]

3.2 Подключаем middleware

Очень важно, чтобы DebugToolbarMiddleware стоял как можно выше, но после django.middleware.common.CommonMiddleware.

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

3.3 Указываем внутренние IP

По умолчанию Debug Toolbar работает только для localhost:

INTERNAL_IPS = [
    '127.0.0.1',
]

3.4 Регистрация URL-маршрута

Открываем cinemahub/urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('movies.urls')),
    path('__debug__/', include('debug_toolbar.urls')),
]

Теперь Debug Toolbar будет доступен на всех страницах.


4. Проверяем работу Debug Toolbar

Запускаем сервер:

python manage.py runserver

Открываем главную страницу проекта, например:

http://127.0.0.1:8000/

Справа появится вертикальная панель Debug Toolbar.

Если панель не появилась, причины могут быть следующие:

Возможные проблемы

Проблема Причина Решение
Панель не видна Не настроены INTERNAL_IPS Нужно указать 127.0.0.1
Страница использует iframe Debug Toolbar не отображается внутри iframe Открыть страницу напрямую
Проект работает не на localhost Debug Toolbar заблокирован Добавить IP в INTERNAL_IPS
Middleware не подключён Пропустили шаг Проверить порядок MIDDLEWARE

5. Понимание панели SQL

Открой страницу с выводом фильмов или жанров.

Например, представим, что в приложении movies есть представление:

def movies_list(request):
    movies = Movie.objects.all()
    return render(request, "movies/list.html", {"movies": movies})

В шаблоне:

{% for movie in movies %}
<p>{{ movie.title }} — {{ movie.genre.name }}</p>
{% endfor %}

На первый взгляд — всё нормально. Но Debug Toolbar в разделе SQL покажет:

  • один запрос на получение фильмов
    • по одному запросу для каждого movie.genre

Если фильмов 20 → получаем 21 SQL-запрос.

Это и называется N+1 проблема.


6. Оптимизация запросов: select_related и prefetch_related

Django предоставляет два основных инструмента оптимизации:

6.1 select_related — для ForeignKey и OneToOne

Загружает связанные данные в одном SQL-запросе:

movies = Movie.objects.all().select_related("genre")

Теперь запросов: 1 вместо 20+1.

6.2 prefetch_related — для ManyToMany и обратных связей

Пример:

movies = Movie.objects.all().prefetch_related("actors")

Django выполнит:

  • один запрос на фильмы,
  • один — на актеров,
  • и сопоставит результаты в Python.

7. Пример оптимизации в проекте cinemahub

Изначальное представление:

def movies_list(request):
    movies = Movie.objects.all()
    return render(request, "movies/list.html", {"movies": movies})

Шаблон выводит:

  • жанр (FK)
  • теги (ManyToMany)

Неблагоприятная ситуация

На 20 фильмов → до 50 SQL-запросов.

Оптимизируем:

def movies_list(request):
    movies = (
        Movie.objects
        .all()
        .select_related("genre")
        .prefetch_related("tags")
    )
    return render(request, "movies/list.html", {"movies": movies})

Что проверяем в браузере?

  1. Обновляем страницу.

  2. Открываем Debug Toolbar → SQL.

  3. Смотрим:

    • количество запросов стало меньше;
    • большая часть данных загрузилась одним JOIN-ом.

8. Частые ошибки студентов

Ошибка 1: select_related на M2M

Movie.objects.select_related("tags")  # неверно

ManyToMany требует prefetch_related.

Ошибка 2: prefetch_related на ForeignKey

Movie.objects.prefetch_related("genre")  # можно, но бессмысленно

Лучше select_related.

Ошибка 3: забыли обновить страницу после изменений

Debug Toolbar показывает данные для текущей страницы, не всегда обновлённые.


9. Не только SQL: другие панели Debug Toolbar

Важные панели:

  • Time — как быстро Django сформировал страницу.
  • Templates — какие шаблоны использовались.
  • Headers — полезно при работе с middleware.
  • Static Files — какие статические файлы загружены.
  • Signals — отображает сигналы Django.

Практический совет

Если страница грузится медленно, но SQL-запросов мало → проблема может быть:

  • в шаблоне,
  • в сложных циклах и фильтрах,
  • в больших статических файлах.

10. Практические задания

Задание 1

Добавьте Django Debug Toolbar в проект cinemahub. Проверьте количество SQL-запросов на странице списка фильмов.

Задание 2

Создайте страницу списка жанров. Проверьте, сколько SQL-запросов выполняется на странице.

Задание 3

Оптимизируйте вывод фильмов так, чтобы на странице выполнялось не более трёх SQL-запросов:

  • фильмы
  • жанры
  • теги

Задание 4

Создайте страницу “Фильмы по жанру”. Оптимизируйте ORM-запросы.

Задание 5

Создайте страницу “Фильмы по актёру”. Используйте prefetch_related для оптимизации.


Вопросы

  1. Для чего используется Django Debug Toolbar?
  2. Почему возникает проблема N+1 запросов?
  3. Какие связи оптимизирует select_related?
  4. Какие связи оптимизирует prefetch_related?
  5. Что произойдёт, если вызвать select_related для поля ManyToMany?
  6. Где в Debug Toolbar можно посмотреть SQL-запросы?
  7. Что показывает панель Templates?
  8. Почему важно проверять результаты оптимизации в браузере?
  9. Можно ли использовать select_related с несколькими полями сразу?
  10. Почему prefetch_related выполняет несколько запросов вместо одного?

Предыдущий урок | Следующий урок