Existe-t-il un moyen de montrer le code SQL exécuté par Django lors de l'exécution d'une requête?
Voir la FAQ de la documentation: " Comment puis-je voir les requêtes SQL brutes que Django exécute? "
Django.db.connection.queries
contient une liste des requêtes SQL:
from Django.db import connection
print connection.queries
Les groupes de requêtes ont également un attribut query
contenant la requête à exécuter:
print MyModel.objects.filter(name="my name").query
Notez que la sortie de la requête n'est pas un code SQL valide, car:
"Django n'interpole jamais réellement les paramètres: il envoie la requête et les paramètres séparément à l'adaptateur de base de données, qui effectue les opérations appropriées."
D'après le rapport de bogue Django # 17741 .
De ce fait, vous ne devez pas envoyer le résultat de la requête directement à une base de données.
Jetez un coup d’œil à debug_toolbar, c’est très utile pour le débogage.
La documentation et les sources sont disponibles sur http://Django-debug-toolbar.readthedocs.io/ .
Django-extensions a une commande Shell_plus avec un paramètre print-sql
./manage.py Shell_plus --print-sql
Dans Django-Shell, toutes les requêtes exécutées seront imprimées.
Ex.:
User.objects.get(pk=1)
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" = 1
Execution time: 0.002466s [Database: default]
<User: username>
Bien que vous puissiez le faire avec le code fourni, je trouve que l’application de la barre d’outils de débogage est un excellent outil pour afficher les requêtes. Vous pouvez le télécharger depuis github ici .
Cela vous donne la possibilité d'afficher toutes les requêtes exécutées sur une page donnée ainsi que le temps nécessaire à l'interrogation. Il résume également le nombre de requêtes sur une page, ainsi que le temps total nécessaire pour une révision rapide. C’est un excellent outil lorsque vous voulez voir ce que l’ORM Django fait en coulisse. Il a également beaucoup d'autres fonctionnalités de Nice, que vous pouvez utiliser si vous le souhaitez.
q = Query.objects.values('val1','val2','val_etc')
print q.query
Aucune autre réponse ne couvre cette méthode, alors:
Je trouve de loin que la méthode la plus utile, la plus simple et la plus fiable consiste à demander votre base de données. Par exemple, sur Linux pour Postgres, vous pouvez effectuer les tâches suivantes:
Sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Chaque base de données aura une procédure légèrement différente. Dans les journaux de la base de données, vous verrez non seulement le SQL brut, mais également toute configuration de connexion ou surcharge de transaction que Django place sur le système.
Une autre option, voir les options de journalisation dans settings.py décrite par cet article.
http://dabapps.com/blog/logging-sql-queries-Django-13/
debug_toolbar ralentit le chargement de chaque page sur votre serveur dev, la journalisation ne le ralentit pas, donc c'est plus rapide. Les sorties peuvent être sauvegardées dans la console ou dans un fichier, l'interface utilisateur n'est donc pas aussi agréable. Toutefois, pour les vues contenant beaucoup de SQL, le débogage et l'optimisation de ces derniers par le biais de debug_toolbar peuvent prendre du temps, car chaque chargement de page est très lent.
Si vous vous assurez que votre fichier settings.py a:
Django.core.context_processors.debug
répertorié dans CONTEXT_PROCESSORS
DEBUG=True
IP
dans le INTERNAL_IPS
TupleEnsuite, vous devriez avoir accès à la variable sql_queries
. J'ajoute un pied de page à chaque page qui ressemble à ceci:
{%if sql_queries %}
<div class="footNav">
<h2>Queries</h2>
<p>
{{ sql_queries|length }} Quer{{ sql_queries|pluralize:"y,ies" }}, {{sql_time_sum}} Time
{% ifnotequal sql_queries|length 0 %}
(<span style="cursor: pointer;" onclick="var s=document.getElementById('debugQueryTable').style;s.disp\
lay=s.display=='none'?'':'none';this.innerHTML=this.innerHTML=='Show'?'Hide':'Show';">Show</span>)
{% endifnotequal %}
</p>
<table id="debugQueryTable" style="display: none;">
<col width="1"></col>
<col></col>
<col width="1"></col>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">SQL</th>
<th scope="col">Time</th>
</tr>
</thead>
<tbody>
{% for query in sql_queries %}
<tr class="{% cycle odd,even %}">
<td>{{ forloop.counter }}</td>
<td>{{ query.sql|escape }}</td>
<td>{{ query.time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
J'ai obtenu la variable sql_time_sum
en ajoutant la ligne
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
à la fonction de débogage dans Django_src/Django/core/context_processors.py.
J'ai développé une extension à cette fin, vous pouvez donc facilement mettre un décorateur sur votre fonction de vue et voir combien de requêtes sont exécutées.
À installer:
$ pip install Django-print-sql
Pour utiliser en tant que gestionnaire de contexte:
from Django_print_sql import print_sql
# set `count_only` to `True` will print the number of executed SQL statements only
with print_sql(count_only=False):
# write the code you want to analyze in here,
# e.g. some complex foreign key lookup,
# or analyzing a DRF serializer's performance
for user in User.objects.all()[:10]:
user.groups.first()
A utiliser comme décorateur:
from Django_print_sql import print_sql_decorator
@print_sql_decorator(count_only=False) # this works on class-based views as well
def get(request):
# your view code here
Je crois que cela devrait fonctionner si vous utilisez PostgreSQL:
from Django.db import connections
from app_name import models
from Django.utils import timezone
# Generate a queryset, use your favorite filter, QS objects, and whatnot.
qs=models.ThisDataModel.objects.filter(user='bob',date__lte=timezone.now())
# Get a cursor tied to the default database
cursor=connections['default'].cursor()
# Get the query SQL and parameters to be passed into psycopg2, then pass
# those into mogrify to get the query that would have been sent to the backend
# and print it out. Note F-strings require python 3.6 or later.
print(f'{cursor.mogrify(*qs.query.sql_with_params())}')
Ce qui suit renvoie la requête en tant que code SQL valide, basé sur https://code.djangoproject.com/ticket/17741 :
def str_query(qs):
"""
qs.query returns something that isn't valid SQL, this returns the actual
valid SQL that's executed: https://code.djangoproject.com/ticket/17741
"""
cursor = connections[qs.db].cursor()
query, params = qs.query.sql_with_params()
cursor.execute('EXPLAIN ' + query, params)
res = str(cursor.db.ops.last_executed_query(cursor, query, params))
assert res.startswith('EXPLAIN ')
return res[len('EXPLAIN '):]
J'ai pu voir les requêtes échouées simplement en faisant:
tail -f /var/log/postgresql/*
Cela supposait que postgres 10.6, ubuntu 18.04+, python3 +, Django2 + et que la journalisation avait été activée dans postgres.
J'ai fait un petit extrait que vous pouvez utiliser:
from Django.conf import settings
from Django.db import connection
def sql_echo(method, *args, **kwargs):
settings.DEBUG = True
result = method(*args, **kwargs)
for query in connection.queries:
print(query)
return result
# HOW TO USE EXAMPLE:
#
# result = sql_echo(my_method, 'whatever', show=True)
Il prend comme fonction de paramètres (contient des requêtes SQL) à inspecter et args, kwargs nécessaires pour appeler cette fonction. Il en résulte que la fonction retourne et imprime les requêtes SQL dans une console.