Лирика
К примеру, требуется вывести в API список пользователей, но не все данные, а только их username, и поэтому queryset=User.objects.only('username'). Допустим, что за один запрос выводится список из 20 пользователей. Теперь мы решили добавить поля first_name и last_name (в сериализатор, но не в queryset). Django Rest Framework перебирает все объекты по очереди. Не обнаружив в текущем объекте поля first_name, django делает запрос в БД за данными этого поля, потом повторяет то же самое для last_name. И так для каждого объекта. В результате имеем один запрос к БД для получения списка объектов и ещё 20 раз по 2 запроса. Итого 41 запрос.
В данном случае достаточно добавить недостающие поля в only или не использовать метод only вовсе. Даже тот, кто знает о коварстве метода only, может не знать об его участии в данном фрагменте кода. А всё потому, что подготовка queryset происходит во view, а использование в serializator. 
Описанный случай, является достаточно экзотичным, но хорошо показывает, как на пустом месте вместо одного запроса можно получить множество. Гораздо чаще приходится прописывать prefetch_related для борьбы с 1+N.
Задействуем мощь отладчика Pycharm
Если при ручном тестировании своего кода мне нужно делать обращение к API, то я всегда включаю вывод логов отладчика, чтобы видеть обращение к БД. Я покажу как это делается, но перед этим вам нужно прочитать
Прочитали? Тогда начинаем.
- Откройте свой проект django и перейдите по ссылке 
CursorDebugWrapper.executeилиCursorDebugWrapper.debug_sqlесли у васDjango 3+ - Поставьте breakpoint на 
logger.debug - Сделайте правый клик на красном кружке
 - В появившимся диалоге отключите 
Suspend - Включите 
Evalute and logи напишите'(%.3f) %s; args=%s'%(duration, sql, params) 
Должно получится так:
Теперь, если вы запустите проект под отладчиком, то увидите в консоли все запросы к БД и время их выполнения. В моём проекте запросов в БД от вызова одного API не очень много и 1+N сразу бросается в глаза, если не включен cacheops. Отключайте cacheops на машине разработки, тогда неправильные запросы к БД вы будете буквально чувствовать на собственной шкуре без всякого логирования и не допустите плохой код в проект.
Главная прелесть логирования через отладчик в том, что не требуется вносить изменения в код, и не придётся убирать за собой забытые print'ы. При этом я не удаляю breakpoint, когда он мне не нужен, а просто выключаю (Ctrl+Shift+F8). А когда становится нужен, снова включаю. Т.е. настроив breakpoint один раз, пользуюсь им всё время.
Но нужно знать 2 вещи. Во-первых, без отладчика эта история не работает. Во-вторых, даже с отладчиком эта история не работает, если у вас mssql aka SQL Server.
Надеюсь, внимательные читатели заметили, что breakpoint стоит не абы где, а на программном логировании, а значит можно просто включить соответствующий уровень логирования в консоль или в файл и получить похожий результат, просто поменяв пару строк кода. Но как это делается вы, наверное, и без меня знаете.
    
    
Top comments (0)