Antworten:
Siehe die häufig gestellten Fragen zu Dokumenten: " Wie kann ich die unformatierten SQL-Abfragen sehen, die Django ausführt? "
django.db.connection.queries
enthält eine Liste der SQL-Abfragen:
from django.db import connection
print(connection.queries)
Abfragesätze haben auch ein query
Attribut, das die auszuführende Abfrage enthält:
print(MyModel.objects.filter(name="my name").query)
Beachten Sie, dass die Ausgabe der Abfrage kein gültiges SQL ist, weil:
"Django interpoliert die Parameter nie wirklich: Es sendet die Abfrage und die Parameter separat an den Datenbankadapter, der die entsprechenden Operationen ausführt."
Aus dem Django-Fehlerbericht # 17741 .
Aus diesem Grund sollten Sie keine Abfrageausgabe direkt an eine Datenbank senden.
str()
Funktion zu verwenden, die die interne __str__()
Methode aufruft . zB str(MyModel.objects.filter(name="my name").query)
würde ich auch mit IPython und die Django - Shell Ihres Projekts empfehlen. Die Tab-Vervollständigung bietet dann eine Selbstbeobachtung des Objekts. Da Django für seine durchsetzungsfähigen Namensschemata bekannt ist, ist diese Methode in der Regel sehr nützlich.
query
SQL nicht gültig ist, da "Django die Parameter nie tatsächlich interpoliert: Es sendet die Abfrage und die Parameter separat an den Datenbankadapter, der die entsprechenden Operationen ausführt." Quelle: code.djangoproject.com/ticket/17741
Django-Erweiterungen haben einen Befehl shell_plus mit einem Parameterprint-sql
./manage.py shell_plus --print-sql
In der Django-Shell werden alle ausgeführten Abfragen gedruckt
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>
Schauen Sie sich debug_toolbar an , es ist sehr nützlich für das Debuggen.
Dokumentation und Quelle finden Sie unter http://django-debug-toolbar.readthedocs.io/ .
q = Query.objects.values('val1','val2','val_etc')
print q.query
m = MyModel.objects.get(...)
gefolgt vonm.query
m
es sich nicht mehr um ein Abfrageset handelt. Verwenden Sie q = MyModel.objects.filter(...)
dann q.query
, dann m = q.get()
.
Keine andere Antwort behandelt diese Methode, also:
Ich finde die mit Abstand nützlichste, einfachste und zuverlässigste Methode, Ihre Datenbank zu fragen. Unter Linux für Postgres können Sie beispielsweise Folgendes tun:
sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Jede Datenbank hat ein etwas anderes Verfahren. In den Datenbankprotokollen sehen Sie nicht nur das unformatierte SQL, sondern auch alle Verbindungsaufbau- oder Transaktionskosten, die Django auf dem System platziert.
log_statement='all'
in postgresql.conf
diesem Verfahren.
postgresql.conf
indem Siepsql -U postgres -c 'SHOW config_file'
Obwohl Sie dies mit dem bereitgestellten Code tun können, finde ich, dass die Verwendung der Debug-Symbolleisten-App ein großartiges Werkzeug ist, um Abfragen anzuzeigen. Sie können es herunterladen von GitHub hier .
Auf diese Weise können Sie alle auf einer bestimmten Seite ausgeführten Abfragen zusammen mit der Zeit anzeigen, die für die Abfrage benötigt wurde. Außerdem wird die Anzahl der Abfragen auf einer Seite zusammen mit der Gesamtzeit für eine schnelle Überprüfung zusammengefasst. Dies ist ein großartiges Tool, wenn Sie einen Blick hinter die Kulissen des Django ORM werfen möchten. Es hat auch viele andere nette Funktionen, die Sie verwenden können, wenn Sie möchten.
Eine weitere Option finden Sie unter Protokollierungsoptionen in settings.py, die in diesem Beitrag beschrieben werden
http://dabapps.com/blog/logging-sql-queries-django-13/
debug_toolbar verlangsamt das Laden jeder Seite auf Ihrem Entwicklungsserver. Die Protokollierung erfolgt nicht, sodass sie schneller ist. Die Ausgaben können in eine Konsole oder eine Datei geschrieben werden, sodass die Benutzeroberfläche nicht so gut ist. Bei Ansichten mit vielen SQLs kann das Debuggen und Optimieren der SQLs über debug_toolbar jedoch lange dauern, da das Laden jeder Seite so langsam ist.
Wenn Sie sicherstellen, dass Ihre Datei settings.py Folgendes enthält:
django.core.context_processors.debug
aufgelistet in CONTEXT_PROCESSORS
DEBUG=True
IP
im INTERNAL_IPS
TupelDann sollten Sie Zugriff auf die sql_queries
Variable haben. Ich füge jeder Seite, die so aussieht, eine Fußzeile hinzu:
{%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 %}
Ich habe die Variable sql_time_sum
durch Hinzufügen der Zeile erhalten
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
zur Debug-Funktion in django_src / django / core / context_processors.py.
Zu diesem Zweck habe ich eine Erweiterung entwickelt, mit der Sie Ihre Ansichtsfunktion einfach mit einem Dekorator versehen und sehen können, wie viele Abfragen ausgeführt werden.
Installieren:
$ pip install django-print-sql
So verwenden Sie als Kontextmanager:
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()
Als Dekorateur verwenden:
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
Ich glaube, das sollte funktionieren, wenn Sie PostgreSQL verwenden:
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())}')
Im Folgenden wird die Abfrage als gültiges SQL basierend auf https://code.djangoproject.com/ticket/17741 zurückgegeben :
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 '):]
Ich habe einen kleinen Ausschnitt erstellt, den Sie verwenden können:
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)
Es wird als Parameterfunktion (enthält SQL-Abfragen) zum Überprüfen und Argumentieren verwendet, kwargs, die zum Aufrufen dieser Funktion benötigt werden. Als Ergebnis wird zurückgegeben, welche Funktion zurückgegeben wird, und SQL-Abfragen werden in einer Konsole gedruckt.
Ich habe diese Funktion in eine Util-Datei in einer der Apps in meinem Projekt eingefügt:
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)))
Dann importiere ich es bei Bedarf einfach und rufe es aus einem beliebigen Kontext (normalerweise einer Ansicht) auf, z. B.:
# ... 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
Es ist schön, dies außerhalb der Vorlage zu tun, denn wenn Sie API-Ansichten haben (normalerweise Django Rest Framework), ist dies auch dort anwendbar.
Für Django 2.2:
Da mir die meisten Antworten bei der Verwendung nicht viel geholfen haben ./manage.py shell
. Endlich habe ich die Antwort gefunden. Hoffe das hilft jemandem.
So zeigen Sie alle Abfragen an:
from django.db import connection
connection.queries
So zeigen Sie die Abfrage für eine einzelne Abfrage an:
q=Query.objects.all()
q.query.__str__()
q.query
Ich zeige nur das Objekt für mich. Bei Verwendung der __str__()
(String-Darstellung) wird die vollständige Abfrage angezeigt.
Anzeigen von Abfragen mit django.db.connection.queries
from django.db import connection
print(connection.queries)
Greifen Sie auf eine unformatierte SQL-Abfrage für das QuerySet-Objekt zu
qs = MyModel.objects.all()
print(qs.query)
Nur um in Django hinzuzufügen, wenn Sie eine Frage haben wie:
MyModel.objects.all()
tun:
MyModel.objects.all().query.sql_with_params()
um die SQL-Zeichenfolge zu erhalten