Логирование в Django: пошаговая настройка и чтение логов
За полчаса вы настроите логирование в Django так, чтобы видеть ошибки в консоли при разработке и складывать их в файл на сервере. Разберём формат сообщений и как отделить логи своего кода от служебных.

По умолчанию Django почти ничего не пишет в лог: при DEBUG = True ошибки видны в браузере, а при DEBUG = False — молча уходят в письмо администратору (если настроена почта) или пропадают. Ниже — как за полчаса собрать конфигурацию, при которой на локальной машине сообщения идут в консоль, а на сервере — в файл с датой, уровнем и именем модуля. Инструкция проверена на Django 5.x, но словарь LOGGING в этом виде работает начиная с Django 1.3.
Что нужно иметь до начала
- работающий проект на Django 4.2 LTS или 5.x — если
python manage.py runserverзапускается, всё готово; - доступ к файлу
settings.pyпроекта (или к модулю настроек, если они разбиты на несколько файлов); - на сервере — право записи в каталог, куда будет писаться файл лога. Это самая частая причина, почему на проде «логи не пишутся»;
- понимание, что логирование в Django — это стандартный модуль Python
logging, а не отдельная библиотека. Django лишь настраивает его через словарь.
Пять уровней, которые надо знать
Каждое сообщение имеет уровень важности. Логгер пропускает сообщения от заданного порога и выше. Порядок по возрастанию:
- DEBUG — подробности для отладки, на проде обычно выключены;
- INFO — штатные события: пользователь вошёл, задача выполнена;
- WARNING — что-то подозрительное, но работает. Уровень по умолчанию;
- ERROR — операция не выполнилась, но приложение живо;
- CRITICAL — приложение не может продолжать работу.
Если вы поставили порог WARNING, сообщения уровня INFO и DEBUG будут отброшены и в файл не попадут.
Шаг 1. Добавьте словарь LOGGING в settings.py
Откройте settings.py и добавьте в конец следующий блок. Он выводит всё в консоль — с этого удобно начать на локальной машине.
# settings.py, Django 5.x
LOGGING = {
"version": 1,
# не отключаем логгеры, которые Django настроил до чтения этого словаря
"disable_existing_loggers": False,
"formatters": {
"verbose": {
"format": "{asctime} [{levelname}] {name}: {message}",
"style": "{",
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "verbose",
},
},
"root": {
"handlers": ["console"],
"level": "INFO",
},
}
Проверка: запустите python manage.py runserver и откройте любую страницу. В консоли, кроме служебных строк сервера, начнут появляться сообщения в формате 2025-01-15 12:00:00,123 [INFO] django.request: .... Если формат другой — значит, обработчик console не подхватился, проверьте отступы в словаре.
Шаг 2. Запишите своё сообщение в лог
В любом файле, где хотите логировать (например, во views.py), получите логгер по имени модуля и вызовите нужный уровень.
# myapp/views.py
import logging
# __name__ даст имя вида "myapp.views" — по нему потом фильтруют
logger = logging.getLogger(__name__)
def checkout(request):
logger.info("Начата оплата заказа для пользователя %s", request.user.id)
try:
# ... логика оплаты ...
pass
except Exception:
# exc_info=True добавит трейсбек в лог
logger.error("Оплата упала", exc_info=True)
raise
return ...
Обратите внимание: аргументы подставляются через %s, а не через f-строку. Так строка форматируется, только если сообщение реально попадёт в лог — это экономит ресурсы на отброшенных DEBUG.
Проверка: вызовите вьюху и найдите в консоли строку с myapp.views. Если её нет, а порог стоит INFO — проверьте, что вы вызываете logger.info, а не logger.debug.
Шаг 3. Добавьте запись в файл для сервера
На проде консоль читать неудобно. Добавьте обработчик, который пишет в файл и сам его ротирует по размеру, чтобы лог не разросся до десятков гигабайт.
# settings.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
LOG_DIR = BASE_DIR / "logs"
LOG_DIR.mkdir(exist_ok=True) # создаём каталог, если его нет
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"verbose": {
"format": "{asctime} [{levelname}] {name}: {message}",
"style": "{",
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "verbose",
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"filename": LOG_DIR / "django.log",
"maxBytes": 10 * 1024 * 1024, # 10 МБ на файл
"backupCount": 5, # хранить 5 старых файлов
"formatter": "verbose",
"encoding": "utf-8",
},
},
"root": {
"handlers": ["console", "file"],
"level": "INFO",
},
}
Проверка: после перезапуска в каталоге logs/ появится файл django.log. Откройте его — там должны быть те же строки, что и в консоли. Пустой файл при непустой консоли почти всегда означает нехватку прав на запись в каталог.
Шаг 4. Разделите свои логи и логи Django
Django ведёт собственные логгеры: django.request (ошибки обработки запросов), django.server (сообщения runserver), django.db.backends (SQL-запросы, если включить). По умолчанию всё стекается в root. Чтобы, например, видеть SQL только при отладке, а свои события — всегда, задайте отдельные логгеры.
# фрагмент LOGGING, добавьте на уровень словаря рядом с "root"
"loggers": {
# ваш код приложения
"myapp": {
"handlers": ["console", "file"],
"level": "DEBUG",
"propagate": False, # не дублировать в root
},
# ошибки запросов Django — только ERROR и выше
"django.request": {
"handlers": ["file"],
"level": "ERROR",
"propagate": False,
},
},
Ключ propagate: False запрещает передавать сообщение вверх по цепочке к root. Без него сообщение из myapp обработается дважды — своим логгером и корневым — и вы увидите дубли в файле.
Порог логгера и порог обработчика перемножаются. Если у логгера уровень DEBUG, а у обработчика — WARNING, до файла дойдут только WARNING и выше. Начинающие часто ставят DEBUG на логгер и удивляются, почему нет отладочных строк — смотрите уровень обработчика.
Как читать лог на сервере
Строка формата 2025-01-15 12:00:00,123 [ERROR] myapp.views: Оплата упала читается так: дата и время, уровень в скобках, имя логгера (по нему понятно, какой модуль писал), затем текст. Полезные команды для файла лога:
tail -f logs/django.log— смотреть новые строки в реальном времени;grep ERROR logs/django.log— вытащить только ошибки;grep "myapp.views" logs/django.log | tail -50— последние 50 записей конкретного модуля.
Если не получилось
- В консоли пусто, хотя сервер работает. Порог стоит выше уровня сообщений — например,
WARNING, а вы шлётеinfo. ПонизьтеlevelуrootдоINFOилиDEBUG. PermissionError: [Errno 13] Permission denied: '.../logs/django.log'— процессу приложения не хватает прав на каталог. Выдайте право записи пользователю, под которым запущен Gunicorn/uWSGI, или укажите путь в каталог, куда он пишет.- ValueError: Unable to configure handler 'file' — обычно неверный путь в
filenameили каталога не существует. Создайте каталог заранее (как в шаге 3 черезmkdir). - Строки дублируются в файле. Логгер пишет и своим обработчиком, и через
root. Добавьтеpropagate: Falseв конкретный логгер. - Не видно SQL-запросов. Это ожидаемо: логгер
django.db.backendsмолчит, пока его уровень не опустить доDEBUGи не работаетDEBUG = True. Включайте только на локальной машине — на проде это лавина строк.
Что настроить дальше
Когда базовое логирование работает, следующий шаг — отправка ошибок в систему мониторинга вместо чтения файла руками. Sentry подключается отдельным SDK и сам ловит необработанные исключения. Ротацию по размеру можно заменить на ротацию по времени через logging.handlers.TimedRotatingFileHandler, если удобнее хранить лог по дням. А формат verbose стоит заменить на JSON, если логи собирает ELK или Loki — тогда их проще фильтровать по полям. Точный список аргументов обработчиков сверяйте с документацией модуля logging вашей версии Python.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: Django documentation — Logging, Python documentation — logging.handlers
Частые вопросы
У меня Django 4.2, а не 5.x — конфигурация подойдёт?
Логи не пишутся в файл на проде, хотя локально всё работает. В чём дело?
Стоит ли включать логирование SQL-запросов на боевом сервере?
Чем RotatingFileHandler лучше обычной записи в файл?
Почему в логе появляются дубликаты одного сообщения?
Нужно ли перезапускать сервер после изменения LOGGING?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.