Jawaban:
Lihat FAQ dokumen: " Bagaimana saya bisa melihat query SQL mentah yang dijalankan Django? "
django.db.connection.queries
berisi daftar kueri SQL:
from django.db import connection
print(connection.queries)
Querysets juga memiliki query
atribut yang berisi kueri yang akan dieksekusi:
print(MyModel.objects.filter(name="my name").query)
Perhatikan bahwa output kueri tidak valid SQL, karena:
"Django tidak pernah benar-benar menginterpolasi parameter: ia mengirimkan permintaan dan parameter secara terpisah ke adaptor basis data, yang melakukan operasi yang sesuai."
Dari laporan bug Django # 17741 .
Karena itu, Anda tidak boleh mengirim output permintaan langsung ke database.
str()
fungsi Pythonian yang ditentukan dan dibangun , yang memanggil __str__()
metode internal . misalnya str(MyModel.objects.filter(name="my name").query)
saya juga akan merekomendasikan menggunakan IPython dan shell Django dari proyek Anda. Tab selesai kemudian memberikan introspeksi objek. Karena Django dikenal dengan skema penamaan yang tegas, metodologi ini cenderung sangat berguna.
query
tidak valid SQL, karena "Django tidak pernah benar-benar menginterpolasi parameter: ia mengirimkan permintaan dan parameter secara terpisah ke adaptor database, yang melakukan operasi yang sesuai." Sumber: code.djangoproject.com/ticket/17741
stable
, bukan dev
, untuk menaut ke versi Django saat ini, seperti ini: docs.djangoproject.com/en/stable/faq/models/…
Django-ekstensi memiliki perintah shell_plus dengan parameterprint-sql
./manage.py shell_plus --print-sql
Dalam django-shell semua query yang dieksekusi akan dicetak
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>
Lihatlah debug_toolbar , ini sangat berguna untuk debugging.
Dokumentasi dan sumber tersedia di http://django-debug-toolbar.readthedocs.io/ .
q = Query.objects.values('val1','val2','val_etc')
print q.query
m = MyModel.objects.get(...)
diikuti olehm.query
m
bukan queryset lagi. Gunakan q = MyModel.objects.filter(...)
, lalu q.query
, lalu m = q.get()
.
Tidak ada jawaban lain yang mencakup metode ini, jadi:
Sejauh ini saya menemukan metode yang paling berguna, sederhana, dan dapat diandalkan untuk menanyakan basis data Anda. Misalnya di Linux untuk Postgres yang mungkin Anda lakukan:
sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Setiap basis data akan memiliki prosedur yang sedikit berbeda. Dalam log basis data Anda tidak hanya akan melihat SQL mentah, tetapi juga pengaturan koneksi atau django overhead transaksi yang ditempatkan pada sistem.
log_statement='all'
dalam postgresql.conf
untuk metode ini.
postgresql.conf
dengan menjalankanpsql -U postgres -c 'SHOW config_file'
Meskipun Anda dapat melakukannya dengan kode yang disediakan, saya menemukan bahwa menggunakan aplikasi bilah alat debug adalah alat yang hebat untuk menampilkan kueri. Anda dapat mengunduhnya dari github di sini .
Ini memberi Anda opsi untuk menampilkan semua kueri yang berlari pada halaman tertentu bersamaan dengan waktu untuk kueri. Itu juga meringkas jumlah pertanyaan pada halaman bersama dengan total waktu untuk tinjauan cepat. Ini adalah alat yang hebat, ketika Anda ingin melihat apa yang dilakukan ORANG Django di belakang layar. Ini juga memiliki banyak fitur bagus lainnya, yang dapat Anda gunakan jika Anda suka.
Opsi lain, lihat opsi masuk dalam pengaturan.py yang dijelaskan oleh posting ini
http://dabapps.com/blog/logging-sql-queries-django-13/
debug_toolbar memperlambat setiap pemuatan halaman di server dev Anda, logging tidak jadi lebih cepat. Keluaran dapat dibuang ke konsol atau file, sehingga UI tidak sebaik. Tetapi untuk tampilan dengan banyak SQL, perlu waktu lama untuk debug dan mengoptimalkan SQL melalui debug_toolbar karena setiap halaman memuat sangat lambat.
Jika Anda memastikan file settings.py Anda memiliki:
django.core.context_processors.debug
tercantum dalam CONTEXT_PROCESSORS
DEBUG=True
IP
di INTERNAL_IPS
tupleMaka Anda harus memiliki akses ke sql_queries
variabel. Saya menambahkan catatan kaki ke setiap halaman yang terlihat seperti ini:
{%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 %}
Saya mendapatkan variabel sql_time_sum
dengan menambahkan baris
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
ke fungsi debug di django_src / django / core / context_processors.py.
Saya mengembangkan ekstensi untuk tujuan ini, sehingga Anda dapat dengan mudah menempatkan dekorator pada fungsi tampilan Anda dan melihat berapa banyak kueri yang dieksekusi.
Untuk memasang:
$ pip install django-print-sql
Untuk digunakan sebagai manajer konteks:
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()
Untuk digunakan sebagai 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
Saya percaya ini harus bekerja jika Anda menggunakan 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())}')
Berikut ini mengembalikan kueri sebagai SQL yang valid, berdasarkan 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 '):]
Saya telah membuat cuplikan kecil yang dapat Anda gunakan:
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)
Dibutuhkan sebagai fungsi parameter (berisi kueri sql) untuk memeriksa dan berargumen, kwargs diperlukan untuk memanggil fungsi itu. Sebagai hasilnya mengembalikan fungsi apa dan mencetak permintaan SQL di konsol.
Saya menempatkan fungsi ini dalam file util di salah satu aplikasi di proyek saya:
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)))
Kemudian, ketika dibutuhkan, saya hanya mengimpornya dan menyebutnya dari konteks apa pun (biasanya tampilan) yang diperlukan, misalnya:
# ... 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
Sangat menyenangkan untuk melakukan ini di luar template karena jika Anda memiliki tampilan API (biasanya Django Rest Framework), itu berlaku juga di sana.
Untuk Django 2.2:
Karena sebagian besar jawaban tidak banyak membantu saya ketika menggunakan ./manage.py shell
. Akhirnya saya menemukan jawabannya. Semoga ini bisa membantu seseorang.
Untuk melihat semua pertanyaan:
from django.db import connection
connection.queries
Untuk melihat permintaan untuk satu permintaan:
q=Query.objects.all()
q.query.__str__()
q.query
hanya menampilkan objek untukku. Menggunakan __str__()
(Representasi string) ditampilkan permintaan penuh.
Lihat Query menggunakan django.db.connection.queries
from django.db import connection
print(connection.queries)
Akses query SQL mentah pada objek QuerySet
qs = MyModel.objects.all()
print(qs.query)
Untuk menambahkan, dalam Django, jika Anda memiliki pertanyaan seperti:
MyModel.objects.all()
melakukan:
MyModel.objects.all().query.sql_with_params()
untuk mendapatkan string sql