Відповіді:
Див. Поширені запитання щодо документів: " Як я можу побачити необроблені запити SQL, які працює Django? "
django.db.connection.queries
містить список запитів SQL:
from django.db import connection
print(connection.queries)
Набори запитів також мають query
атрибут, що містить запит, який потрібно виконати:
print(MyModel.objects.filter(name="my name").query)
Зауважте, що вихід запиту не є дійсним SQL, оскільки:
"Django ніколи фактично не інтерполює параметри: він надсилає запит та параметри окремо на адаптер бази даних, який виконує відповідні операції."
З повідомлення про помилку Django # 17741 .
Через це не слід надсилати запити безпосередньо в базу даних.
str()
функцію пітона , яка викликає внутрішній __str__()
метод. Наприклад, str(MyModel.objects.filter(name="my name").query)
я б також рекомендував використовувати IPython та оболонку Django для вашого проекту. Завершення вкладки потім забезпечує самоаналіз об'єкта. Оскільки Джанго відомий своїми твердими схемами називання, ця методологія, як правило, дуже корисна.
query
не є дійсним SQL, оскільки "Django ніколи фактично не інтерполює параметри: він надсилає запит та параметри окремо на адаптер бази даних, який виконує відповідні операції." Джерело: code.djangoproject.com/ticket/17741
stable
не dev
для посилання на поточну версію Django, наприклад: docs.djangoproject.com/en/stable/faq/models/…
У розширеннях Django є команда shell_plus з параметромprint-sql
./manage.py shell_plus --print-sql
У оболонці django всі виконані запити будуть надруковані
Наприклад:
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>
Погляньте на debug_toolbar , це дуже корисно для налагодження.
Документація та джерело доступні на веб- сайті http://django-debug-toolbar.readthedocs.io/ .
q = Query.objects.values('val1','val2','val_etc')
print q.query
m = MyModel.objects.get(...)
супроводжуюсьm.query
m
це вже не набір запитів. Використовуйте q = MyModel.objects.filter(...)
, тоді q.query
, тоді m = q.get()
.
Жодна інша відповідь не охоплює цей метод, тому:
Я вважаю, що найбільш корисним, простим та надійним методом є запитання у вашій базі даних. Наприклад, для Linux для Postgres ви можете:
sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Кожна база даних матиме дещо іншу процедуру. У журналах баз даних ви побачите не тільки необроблений SQL, але і будь-яку установку з'єднання або транзакцію, накладну на django, що розміщується в системі.
log_statement='all'
в postgresql.conf
протягом цього методу.
postgresql.conf
, запустившиpsql -U postgres -c 'SHOW config_file'
Хоча ви можете зробити це за допомогою наданого коду, я вважаю, що використання програми панелі інструментів налагодження є чудовим інструментом для показу запитів. Ви можете завантажити його з Github тут .
Це дає вам змогу показувати всі запити, виконані на певній сторінці, а також час запиту. Він також підсумовує кількість запитів на сторінці разом із загальним часом для швидкого огляду. Це чудовий інструмент, коли ви хочете подивитися, що робить Django ORM за лаштунками. Він також має багато інших приємних функцій, якими ви можете користуватися, якщо хочете.
Інший варіант, див. Параметри журналу в налаштуваннях.py, описані цією публікацією
http://dabapps.com/blog/logging-sql-queries-django-13/
debug_toolbar уповільнює завантаження кожної сторінки на вашому сервері розробок, реєстрація не є швидшою. Виходи можна скинути на консоль чи файл, тому інтерфейс користувача не такий приємний. Але для переглядів з великою кількістю SQL може знадобитися тривалий час налагодження та оптимізації SQL через debug_toolbar, оскільки завантаження кожної сторінки відбувається настільки повільно.
Якщо ви переконайтеся, що ваш файл settings.py має:
django.core.context_processors.debug
вказані в CONTEXT_PROCESSORS
DEBUG=True
IP
у INTERNAL_IPS
кортежіТоді ви повинні мати доступ до sql_queries
змінної. Я додаю колонтитул до кожної сторінки, який виглядає приблизно так:
{%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 %}
Я отримав змінну sql_time_sum
, додавши рядок
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
до функції налагодження в django_src / django / core / context_processors.py.
Для цього я розробив розширення, тому ви можете легко поставити декоратор на функцію перегляду і подивитися, скільки запитів виконано.
Щоб встановити:
$ pip install django-print-sql
Щоб використовувати як менеджер контексту:
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()
Для використання в якості декоратора:
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
Я вважаю, що це має спрацювати, якщо ви використовуєте 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())}')
Далі повертає запит як дійсний SQL на основі 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 '):]
Я зробив невеликий фрагмент, який ви можете використовувати:
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)
Функція параметрів приймає функцію параметрів (містить запити sql) для перевірки та аргументів, kwargs, необхідних для виклику цієї функції. Як результат, він повертає те, що функція повертає та друкує SQL-запити в консолі.
Я поміщаю цю функцію у файл утиліти в одному з додатків мого проекту:
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)))
Потім, коли це потрібно, я просто імпортую його та називаю з будь-якого контексту (як правило, перегляду), наприклад:
# ... 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
Приємно це робити за межами шаблону, тому що тоді, якщо у вас є перегляди API (зазвичай Django Rest Framework), це також застосовно.
Для Джанго 2.2:
Оскільки більшість відповідей мені не дуже допомогли при використанні ./manage.py shell
. Нарешті я знайшов відповідь. Сподіваюсь, це комусь допомагає.
Щоб переглянути всі запити:
from django.db import connection
connection.queries
Щоб переглянути запит на один запит:
q=Query.objects.all()
q.query.__str__()
q.query
просто показ об’єкта для мене. За допомогою __str__()
(String уявлення) відображається повний запит.
Перегляд запитів за допомогою django.db.connection.queries
from django.db import connection
print(connection.queries)
Доступ до необмеженого запиту SQL на об’єкт QuerySet
qs = MyModel.objects.all()
print(qs.query)
Просто додати в django, якщо у вас є запит, наприклад:
MyModel.objects.all()
робити:
MyModel.objects.all().query.sql_with_params()
щоб отримати рядок sql