Câu trả lời:
Xem Câu hỏi thường gặp về tài liệu: " Làm cách nào tôi có thể thấy các truy vấn SQL thô mà Django đang chạy? "
django.db.connection.queries
chứa danh sách các truy vấn SQL:
from django.db import connection
print(connection.queries)
Các truy vấn cũng có một query
thuộc tính chứa truy vấn sẽ được thực thi:
print(MyModel.objects.filter(name="my name").query)
Lưu ý rằng đầu ra của truy vấn không phải là SQL hợp lệ, bởi vì:
"Django thực sự không bao giờ nội suy các tham số: nó gửi truy vấn và các tham số riêng biệt đến bộ điều hợp cơ sở dữ liệu, thực hiện các hoạt động thích hợp."
Từ báo cáo lỗi Django # 17741 .
Do đó, bạn không nên gửi đầu ra truy vấn trực tiếp đến cơ sở dữ liệu.
str()
hàm Pythonia được chỉ định, dựng sẵn , gọi __str__()
phương thức bên trong . ví dụ: str(MyModel.objects.filter(name="my name").query)
tôi cũng khuyên bạn nên sử dụng IPython và shell Django trong dự án của bạn. Tab hoàn thành sau đó cung cấp nội quan đối tượng. Vì Django được biết đến với các kế hoạch đặt tên quyết đoán, phương pháp này có xu hướng rất hữu ích.
query
SQL không hợp lệ, bởi vì "Django thực sự không bao giờ nội suy các tham số: nó gửi truy vấn và các tham số riêng biệt đến bộ điều hợp cơ sở dữ liệu, thực hiện các hoạt động thích hợp." Nguồn: code.djangoproject.com/ticket/17741
stable
, không dev
, để liên kết với phiên bản hiện tại của Django, như thế này: docs.djangoproject.com/en/ sóng / faq / models / khăn
Phần mở rộng Django có lệnh shell_plus với tham sốprint-sql
./manage.py shell_plus --print-sql
Trong django-shell, tất cả các truy vấn được thực hiện sẽ được in
Ví dụ.:
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>
Hãy xem debug_toolbar , nó rất hữu ích để gỡ lỗi.
Tài liệu và nguồn có sẵn tại http://django-debug-toolbar.readthedocs.io/ .
q = Query.objects.values('val1','val2','val_etc')
print q.query
m = MyModel.objects.get(...)
theo saum.query
m
không phải là một truy vấn nữa. Sử dụng q = MyModel.objects.filter(...)
, sau đó q.query
, sau đó m = q.get()
.
Không có câu trả lời khác bao gồm phương pháp này, vì vậy:
Tôi thấy rằng phương pháp hữu ích, đơn giản và đáng tin cậy nhất là hỏi cơ sở dữ liệu của bạn. Ví dụ: trên Linux cho Postgres bạn có thể làm:
sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Mỗi cơ sở dữ liệu sẽ có thủ tục hơi khác nhau. Trong nhật ký cơ sở dữ liệu, bạn sẽ thấy không chỉ SQL thô, mà bất kỳ thiết lập kết nối hoặc django giao dịch nào đang được đặt trên hệ thống.
log_statement='all'
trong postgresql.conf
cho phương pháp này.
postgresql.conf
bằng cách chạypsql -U postgres -c 'SHOW config_file'
Mặc dù bạn có thể làm điều đó với mã được cung cấp, tôi thấy rằng sử dụng ứng dụng thanh công cụ gỡ lỗi là một công cụ tuyệt vời để hiển thị các truy vấn. Bạn có thể tải nó từ github tại đây .
Điều này cung cấp cho bạn tùy chọn hiển thị tất cả các truy vấn đã chạy trên một trang nhất định cùng với thời gian truy vấn đã thực hiện. Nó cũng tổng hợp số lượng truy vấn trên một trang cùng với tổng thời gian để đánh giá nhanh. Đây là một công cụ tuyệt vời, khi bạn muốn xem những gì Django ORM làm đằng sau hậu trường. Nó cũng có rất nhiều tính năng hay khác, mà bạn có thể sử dụng nếu bạn thích.
Một tùy chọn khác, xem các tùy chọn đăng nhập trong settings.txt được mô tả bởi bài đăng này
http://dabapps.com/blog/logging-sql-queries-django-13/
debug_toolbar làm chậm tải mỗi trang trên máy chủ dev của bạn, đăng nhập không vì thế nó nhanh hơn. Đầu ra có thể được đổ vào bàn điều khiển hoặc tập tin, vì vậy giao diện người dùng không đẹp. Nhưng đối với các chế độ xem có nhiều SQL, có thể mất nhiều thời gian để gỡ lỗi và tối ưu hóa các SQL thông qua debug_toolbar vì mỗi lần tải trang quá chậm.
Nếu bạn chắc chắn rằng tệp cài đặt của bạn có:
django.core.context_processors.debug
được liệt kê trong CONTEXT_PROCESSORS
DEBUG=True
IP
trong INTERNAL_IPS
tuple của bạnSau đó, bạn nên có quyền truy cập vào các sql_queries
biến. Tôi nối một chân trang vào mỗi trang giống như thế này:
{%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 %}
Tôi đã nhận được biến sql_time_sum
bằng cách thêm dòng
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
đến chức năng gỡ lỗi trong django_src / django / core / context_ Processors.py.
Tôi đã phát triển một tiện ích mở rộng cho mục đích này, vì vậy bạn có thể dễ dàng đặt một trình trang trí vào chức năng xem của mình và xem có bao nhiêu truy vấn được thực hiện.
Để cài đặt:
$ pip install django-print-sql
Để sử dụng làm trình quản lý bối cảnh:
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()
Để sử dụng như trang trí:
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
Tôi tin rằng điều này nên hoạt động nếu bạn đang sử dụng 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())}')
Sau đây trả về truy vấn dưới dạng SQL hợp lệ, dựa trên 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 '):]
Tôi đã tạo một đoạn nhỏ bạn có thể sử dụng:
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)
Nó có chức năng như tham số (chứa các truy vấn sql) để kiểm tra và lập luận, các kwarg cần thiết để gọi hàm đó. Kết quả là nó trả về hàm nào trả về và in các truy vấn SQL trong bàn điều khiển.
Tôi đặt chức năng này trong một tệp sử dụng trong một trong các ứng dụng trong dự án của mình:
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)))
Sau đó, khi cần, tôi chỉ cần nhập nó và gọi nó từ bất kỳ bối cảnh nào (thường là chế độ xem) là cần thiết, ví dụ:
# ... 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
Thật tuyệt khi làm điều này bên ngoài mẫu bởi vì sau đó nếu bạn có chế độ xem API (thường là Django Rest Framework), thì nó cũng có thể áp dụng được.
Đối với Django 2.2:
Vì hầu hết các câu trả lời không giúp tôi nhiều khi sử dụng ./manage.py shell
. Cuối cùng tôi cũng tìm được câu trả lời. Hy vọng điều này sẽ giúp cho một ai đó.
Để xem tất cả các truy vấn:
from django.db import connection
connection.queries
Để xem truy vấn cho một truy vấn duy nhất:
q=Query.objects.all()
q.query.__str__()
q.query
chỉ hiển thị các đối tượng cho tôi. Sử dụng __str__()
(Biểu diễn chuỗi) hiển thị toàn bộ truy vấn.
Xem Truy vấn bằng django.db.connection.queries
from django.db import connection
print(connection.queries)
Truy cập truy vấn SQL thô trên đối tượng Queryset
qs = MyModel.objects.all()
print(qs.query)
Chỉ cần thêm, trong django, nếu bạn có một truy vấn như:
MyModel.objects.all()
làm:
MyModel.objects.all().query.sql_with_params()
để có được chuỗi sql