Релизнул встраиваемое приложение "django-sql-stacktrace"
Это приложение записывает python stack trace в SQL-запрос как коментарий. Это бывает полезно во время откладки проекта, когда вы видите много SQL-запросов и не понимаете откуда они были вызваны.
PyPI: django-sql-stacktrace
Для примера, вы попали в новый проект и вас попросили исправить проблему с большим количеством запросов к БД. Вы открываете processlist ("mysqladmin processlist --verbose") и видите множество различных запросов:
... SELECT COUNT(*) FROM `films_film` INNER JOIN `films_year` ON (`films_film`.`year_id` = `films_year`.`id`) WHERE (`films_film`.`status` = 'published' AND `films_year`.`id` IS NOT NULL); SELECT `blogs_post`.`id`, `blogs_post`.`blog_id`, `blogs_post`.`title`, `blogs_post`.`slug`, `blogs_post`.`status`, `blogs_post`.`created`, `blogs_post`.`updated`, `blogs_post`.`published`, `blogs_post`.`description`, `blogs_post`.`thumbnail`, `blogs_post`.`content`, `blogs_post`.`count_of_views`, `blogs_post`.`source_content`, `blogs_post`.`source_published`, `blogs_post`.`source_count_views`, `blogs_post`.`source_author_of_content`, `blogs_post`.`source_author_of_photo`, `blogs_post`.`source_keywords`, `blogs_post`.`source_url` FROM `blogs_post` WHERE `blogs_post`.`status` = 'published' ORDER BY `blogs_post`.`published` DESC LIMIT 4; SELECT `social_auth_usersocialauth`.`id`, `social_auth_usersocialauth`.`user_id`, `social_auth_usersocialauth`.`provider`, `social_auth_usersocialauth`.`uid`, `social_auth_usersocialauth`.`extra_data` FROM `social_auth_usersocialauth` WHERE `social_auth_usersocialauth`.`user_id` = 42; SELECT `films_film`.`id`, `films_film`.`status`, `films_film`.`created`, `films_film`.`updated`, `films_film`.`published`, `films_film`.`title_original`, `films_film`.`title_ru`, `films_film`.`slug`, `films_film`.`thumbnail`, `films_film`.`slogan`, `films_film`.`description`, `films_film`.`date_premiere`, `films_film`.`year_id`, `films_film`.`rating_votes`, `films_film`.`rating_score`, `films_film`.`rating_score_with_vote_weight`, `films_year`.`id`, `films_year`.`name`, `films_year`.`count`, `films_year`.`size` FROM `films_film` LEFT OUTER JOIN `films_year` ON (`films_film`.`year_id` = `films_year`.`id`) WHERE (`films_film`.`status` = 'published' AND `films_year`.`id` IS NOT NULL) ORDER BY `films_film`.`published` DESC LIMIT 30; ...
Где они были вызваны вы не знаете, более того, это не только SQL-запросы из вьюх проекта, это так же запросы из команд, демонов каких-то, вообщем куча неизветсно откуда запросов. Как вам понять где эти запросы вызываются?
Нет проблем! Вы берете django-sql-stacktrace, запускаете свою локальную копию проекта (а на деле может пригодится и на продакшене) и увидите следующее:
... SELECT COUNT(*) FROM `films_film` INNER JOIN `films_year` ON (`films_film`.`year_id` = `films_year`.`id`) WHERE (`films_film`.`status` = 'published' AND `films_year`.`id` IS NOT NULL) /* STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/kinsburg_tv/common/views.py", line 27, in get_context_data > context = super(MainPage, self).get_context_data(**kwargs) STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/kinsburg_tv/films/mixins.py", line 14, in get_context_data > context = super(FilmsMixin, self).get_context_data(**kwargs) STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 351, in count > return self.query.get_count(using=self.db) STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 418, in get_count > number = obj.get_aggregation(using=using)[None] STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 384, in get_aggregation > result = query.get_compiler(using).execute_sql(SINGLE) STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 818, in execute_sql > cursor.execute(sql, params) STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/venv/local/lib/python2.7/site-packages/sqlstacktrace/stacktracecursor.py", line 16, in execute > stacks = get_stacktrace() STACKTRACE: > File "/home/adw0rd/work/kinsburg_tv/venv/local/lib/python2.7/site-packages/sqlstacktrace/stacktrace.py", line 93, in get_stacktrace > stack = get_stack() */; ...
Отличная работа! Теперь вы знаете откуда произошел вызов того или инного запроса, осталось только исправить эту проблему.
Установка и настройка
Вы можете установить с PyPI:
pip install django-sql-stacktrace
Или установить dev-версию с GitHub:
pip install -e git://github.com/adw0rd/django-sql-stacktrace.git#egg=sqlstacktrace
Теперь, добавьте в "INSTALLED_APPS":
INSTALLED_APPS = ( ... 'sqlstacktrace', ... )
И включите SQL_STACKTRACE:
SQL_STACKTRACE = True
Получение исходного кода
Вы можете получить django-sql-stacktrace на
Комментарии
а может уже будешь делать на несколько языках? :)
Пока тренируюсь, завтра переведу скорее всего на русский...
Последующие статьи на английском буду сразу переводить на русский, а русские на английский вряд ли буду
Готово!
Не работает для админки
Хм, надо посмотреть как для админки используется CursorWrapper
Я проверил, зашел в админку, смотрю в SQL-панель django-debug-toolbar и вижу трейсбек. Вы точно указали приложение в INSTALLED_APPS и указали SQL_STACKTRACE=True?
Оставьте свой комментарий