Réponses:
Voir la FAQ de la documentation: " Comment puis-je voir les requêtes SQL brutes exécutées par Django? "
django.db.connection.queries
contient une liste des requêtes SQL:
from django.db import connection
print(connection.queries)
Les ensembles de requêtes ont également un query
attribut 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 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 de Django # 17741 .
Pour cette raison, vous ne devez pas envoyer de sortie de requête directement à une base de données.
str()
fonction Pythonian intégrée spécifiée , qui appelle la __str__()
méthode interne . par exemple, str(MyModel.objects.filter(name="my name").query)
je recommanderais également d'utiliser IPython et le shell Django de votre projet. L'achèvement des tabulations permet ensuite l'introspection des objets. Comme Django est connu pour ses schémas de nommage assertifs, cette méthodologie a tendance à être très utile.
query
SQL n'est pas 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." Source: code.djangoproject.com/ticket/17741
stable
, non dev
, pour créer un lien vers la version actuelle de Django, comme ceci: docs.djangoproject.com/en/stable/faq/models/…
Les extensions Django ont une commande shell_plus avec un paramètreprint-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>
Jetez un œil à debug_toolbar , il est très utile pour le débogage.
La documentation et la source sont disponibles sur http://django-debug-toolbar.readthedocs.io/ .
q = Query.objects.values('val1','val2','val_etc')
print q.query
m = MyModel.objects.get(...)
suivi parm.query
m
n'est plus un ensemble de requêtes. Utilisez q = MyModel.objects.filter(...)
, alors q.query
, alors m = q.get()
.
Aucune autre réponse ne couvre cette méthode, donc:
Je trouve que la méthode de loin la plus utile, la plus simple et la plus fiable est de demander à votre base de données. Par exemple, sur Linux pour Postgres, vous pourriez faire:
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 base de données, vous verrez non seulement le SQL brut, mais toute configuration de connexion ou surcharge de transaction que Django place sur le système.
log_statement='all'
dans postgresql.conf
cette méthode.
postgresql.conf
en exécutantpsql -U postgres -c 'SHOW config_file'
Bien que vous puissiez le faire avec le code fourni, je trouve que l'utilisation de l'application de 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 à la requête. Il résume également le nombre de requêtes sur une page ainsi que le temps total pour un examen rapide. C'est un excellent outil, lorsque vous voulez voir ce que fait Django ORM dans les coulisses. Il possède également de nombreuses autres fonctionnalités intéressantes que vous pouvez utiliser si vous le souhaitez.
Une autre option, voir les options de journalisation dans settings.py décrites par cet article
http://dabapps.com/blog/logging-sql-queries-django-13/
debug_toolbar ralentit chaque chargement de page sur votre serveur de développement, la journalisation ne l'est pas donc c'est plus rapide. Les sorties peuvent être sauvegardées sur console ou fichier, donc l'interface utilisateur n'est pas aussi agréable. Mais pour les vues avec beaucoup de SQL, le débogage et l'optimisation des SQL peuvent prendre du temps via debug_toolbar, car chaque chargement de page est si 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 sql_queries
variable. 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 à cet effet, afin que vous puissiez facilement mettre un décorateur sur votre fonction d'affichage et voir combien de requêtes sont exécutées.
À installer:
$ pip install django-print-sql
Pour utiliser comme 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()
Pour 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 pense 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 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 créé 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 paramètres (contient des requêtes SQL) pour inspecter et args, les kwargs nécessaires pour appeler cette fonction. En conséquence, il renvoie la fonction renvoyée et imprime les requêtes SQL dans une console.
J'ai mis cette fonction dans un fichier util dans l'une des applications de mon projet:
import logging
import re
from django.db import connection
logger = logging.getLogger(__name__)
def sql_logger():
logger.debug('TOTAL QUERIES: ' + str(len(connection.queries)))
logger.debug('TOTAL TIME: ' + str(sum([float(q['time']) for q in connection.queries])))
logger.debug('INDIVIDUAL QUERIES:')
for i, query in enumerate(connection.queries):
sql = re.split(r'(SELECT|FROM|WHERE|GROUP BY|ORDER BY|INNER JOIN|LIMIT)', query['sql'])
if not sql[0]: sql = sql[1:]
sql = [(' ' if i % 2 else '') + x for i, x in enumerate(sql)]
logger.debug('\n### {} ({} seconds)\n\n{};\n'.format(i, query['time'], '\n'.join(sql)))
Ensuite, au besoin, je l'importe et l'appelle à partir de n'importe quel contexte (généralement une vue) nécessaire, par exemple:
# ... other imports
from .utils import sql_logger
class IngredientListApiView(generics.ListAPIView):
# ... class variables and such
# Main function that gets called when view is accessed
def list(self, request, *args, **kwargs):
response = super(IngredientListApiView, self).list(request, *args, **kwargs)
# Call our function
sql_logger()
return response
C'est agréable de le faire en dehors du modèle, car si vous avez des vues API (généralement Django Rest Framework), cela s'applique également là-bas.
Pour Django 2.2:
Comme la plupart des réponses ne m'ont pas beaucoup aidé lors de l'utilisation ./manage.py shell
. Enfin, j'ai trouvé la réponse. J'espère que cela aide quelqu'un.
Pour afficher toutes les requêtes:
from django.db import connection
connection.queries
Pour afficher une requête pour une seule requête:
q=Query.objects.all()
q.query.__str__()
q.query
juste afficher l'objet pour moi. L'utilisation de la __str__()
(représentation de chaîne) affiche la requête complète.
Afficher les requêtes à l' aide de django.db.connection.queries
from django.db import connection
print(connection.queries)
Accéder à une requête SQL brute sur un objet QuerySet
qs = MyModel.objects.all()
print(qs.query)
Juste pour ajouter, dans django, si vous avez une requête comme:
MyModel.objects.all()
faire:
MyModel.objects.all().query.sql_with_params()
pour obtenir la chaîne sql