Afficher le queryset d’une requête dans les logs SQL sous Django


C’est Noël, 2 articles rien que pour vous dont un très interressant de Sam.

L’ORM de django pour les bases de données est chouette, agréable à utiliser mais construit des requêtes SQL qu’on ne peut reconnaître lors de l’analyse des logs MYSQL du premier coup d’oeil. Et quand on a des centaines de requêtes par secondes c’est carrément impossible de s’y retrouver.

Ce que je vous propose ici c’est d’afficher le queryset (sa ligne et le fichier qui le contient) qui a permit d’exêcuter la requête SQL que vous voyez défiler dans les logs SQL sous forme de commentaires SQL.

L’application se nomme Django Sql StackTrace. C’est facile à installer et ça peut sauver des heures de debug.

Installation Django Sql StackTrace:

Une bonne PIP comme toujours pour bien commencer.

pip install django-sql-stacktrace

Dans votre fichier settings de django.

INSTALLED_APPS = (
    .........................
    'sqlstacktrace',
    .........................
)
 
SQL_STACKTRACE = True

La variable SQL_STACKTRACE sert à activer le debug.
Pensez à le désactiver lorsque vous n’en avez pas besoin.

Où se trouve mes super infos de debug ?

D’après la doc vous pouvez executer un watch

watch -n1 mysqladmin -u login -pmot_de_passe processlist --verbose

Chez moi ça n’a rien donné. Mais du côté des logs MySQL la magie a opérée.
Vérifiez tout d’abord que vos logs sont activés dans mysql.

vi /etc/my.cnf
[mysqld]
......
log = /var/logs/mysql.log
......

Comment on teste ça ?

Redemarrez votre serveur web, surfez sur les pages de votre projet et observez les logs MySql. Vous deviez voir quelques chose de similaire:

tail -F /var/logs/mysql.log
		  644 Query	SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 65290
/* File "/Users/max/work/mon_projet/apps/mon_apps/views/others.py", line 146, in user_public_page
	user = User.objects.get(pk=user_id)
*/

Observez cette merveille !
Entre /* */ sont les infos générées par django-sql-stacktrace. J’ai nettoyé quelques fichiers pour plus de lisibilité.
Vous avez droit au chemin du fichier de la requête, à la ligne de la requête et à la requête django elle-même.

Une alternative ? J’ai pas envie d’installer d’app.

Pour les grosses feignasses ou si vous voulez juste tester occasionnellement quelques queries vous pouvez utiliser la méthode extra pour ajouter vos propres commentaires.

videos = Video.objects.filter(status='online').extra(where=['1=1 /* ceci apparaitra dans les logs mysql ! */'])

Cependant le WHERE 1=1 peut causer quelques baisses de performances, mais lorsqu’on est en debug en local ça peut servir !

PS: Je rappelle également le formidable outil django-debug-toolbar qui devient vite indispensable.

Alors ? Elle est pas belle la vie ?

2 thoughts on “Afficher le queryset d’une requête dans les logs SQL sous Django

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.