Jak Mogę zobaczyć uruchomione surowe zapytania SQL Django?
Czy istnieje sposób, aby pokazać SQL, który Django uruchamia podczas wykonywania zapytania?
16 answers
Zobacz FAQ docs: "Jak mogę zobaczyć uruchomione surowe zapytania SQL Django?"
django.db.connection.queries
zawiera listę zapytań SQL:
from django.db import connection
print(connection.queries)
Querysets mają równieżquery
atrybut zawierający zapytanie do wykonania:
print(MyModel.objects.filter(name="my name").query)
Zauważ, że wyjście zapytania nie jest poprawne SQL, ponieważ:
"Django nigdy w rzeczywistości nie interpoluje parametrów: wysyła zapytanie i parametry oddzielnie do adaptera bazy danych, który wykonuje odpowiednie operacje."
From Django bug report #17741.
Z tego powodu nie należy wysyłać zapytania bezpośrednio do bazy danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-30 04:32:45
Django-rozszerzenia mają polecenie shell_plus z parametrem print-sql
./manage.py shell_plus --print-sql
W django-shell wydrukowane zostaną wszystkie wykonane zapytania
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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-16 09:43:29
Spójrz na debug_toolbar , jest bardzo przydatny do debugowania.
Dokumentacja i źródło są dostępne na stronie http://django-debug-toolbar.readthedocs.io/.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-14 17:38:58
Żadna inna odpowiedź nie obejmuje tej metody, więc:
Uważam, że zdecydowanie najbardziej użyteczną, prostą i niezawodną metodą jest zapytanie bazy danych. Na przykład w Linuksie dla Postgres można zrobić:
sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Każda baza danych będzie miała nieco inną procedurę. W logach bazy danych zobaczysz nie tylko surowy SQL, ale także wszelkie ustawienia połączenia lub transakcje, które django umieszcza w systemie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-31 23:31:22
Zapytanie jest faktycznie osadzone w API modeli:
q = Query.objects.values('val1','val2','val_etc')
print(q.query)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-12 10:56:30
Chociaż możesz to zrobić za pomocą dostarczonego kodu, uważam, że korzystanie z aplikacji debug toolbar jest świetnym narzędziem do wyświetlania zapytań. Możesz go pobrać z github tutaj .
Daje to możliwość pokazania wszystkich zapytań uruchomionych na danej stronie wraz z czasem, jaki zajęło zapytanie. Podsumowuje również liczbę zapytań na stronie wraz z całkowitym czasem na szybki przegląd. Jest to świetne narzędzie, gdy chcesz zobaczyć, co Django ORM robi za kulisami. Ma również wiele inne ładne funkcje, które możesz użyć, jeśli chcesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-02 13:47:29
Inna opcja, zobacz Opcje logowania w settings.py opisane przez ten post
Http://dabapps.com/blog/logging-sql-queries-django-13/
Debug_toolbar spowalnia każde obciążenie strony na serwerze dev, logowanie NIE JEST więc szybsze. Wyjścia mogą być przesyłane do konsoli lub pliku, więc interfejs użytkownika nie jest tak miły. Ale w przypadku widoków z dużą ilością SQL debugowanie i optymalizacja SQL za pomocą debug_toolbar może zająć dużo czasu, ponieważ każde ładowanie strony jest tak powolne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-27 15:45:16
Jeśli upewnisz się, że Twoje settings.py plik ma:
-
django.core.context_processors.debug
wymienione wCONTEXT_PROCESSORS
DEBUG=True
- twoje
IP
wINTERNAL_IPS
krotce
Wtedy powinieneś mieć dostęp do zmiennej sql_queries
. Dodaję stopkę do każdej strony, która wygląda tak:
{%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 %}
Otrzymałem zmienną sql_time_sum
dodając linię
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
Do funkcji debugowania w django_src/django/core/context_processors.py.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-16 19:01:07
W tym celu opracowałem rozszerzenie, dzięki któremu można łatwo umieścić dekorator w funkcji widoku i zobaczyć, ile zapytań jest wykonywanych.
Aby zainstalować:
$ pip install django-print-sql
Aby użyć jako menedżera kontekstu:
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()
Do użycia jako dekorator:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-16 10:36:06
Wystarczy dodać, w django, jeśli masz zapytanie takie jak:
MyModel.objects.all()
Do:
MyModel.objects.all().query.sql_with_params()
Lub:
str(MyModel.objects.all().query)
Aby uzyskać ciąg sql
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-26 06:50:30
Uważam, że to powinno zadziałać, jeśli używasz 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())}')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-31 14:16:36
Umieściłem tę funkcję w pliku util w jednej z aplikacji w moim projekcie:
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)))
Wtedy, gdy jest to potrzebne, po prostu importuję go i wywołuję z dowolnego kontekstu (Zwykle widoku), np.:
# ... 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
Miło jest to zrobić poza szablonem, ponieważ wtedy, jeśli masz widoki API (Zwykle Django Rest Framework), to również tam się znajduje zastosowanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-15 00:35:02
Poniższe zapytanie zwraca jako poprawny SQL, na podstawie 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 '):]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-29 00:01:15
Zrobiłem mały fragment, którego możesz użyć:
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)
Przyjmuje jako funkcję parametrów (zawiera zapytania sql) inspect i args, kwargs potrzebne do wywołania tej funkcji. W rezultacie zwraca to, co funkcja zwraca i wyświetla zapytania SQL w konsoli.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-25 10:23:56
Dla Django 2.2:
Ponieważ większość odpowiedzi nie pomogła mi zbytnio przy użyciu ./manage.py shell
. W końcu znalazłem odpowiedź. Mam nadzieję, że to komuś pomoże.
Aby wyświetlić wszystkie zapytania:
from django.db import connection
connection.queries
Aby wyświetlić zapytanie dla pojedynczego zapytania:
q=Query.objects.all()
q.query.__str__()
q.query
tylko pokazuję mi obiekt.
Użycie __str__()
(reprezentacja łańcuchowa) wyświetla pełne zapytanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-03 19:18:59
View Queries using django.db.połączenie.queries
from django.db import connection
print(connection.queries)
Dostęp do surowego zapytania SQL na obiekcie QuerySet
qs = MyModel.objects.all()
print(qs.query)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-01 10:28:28