Yanıtlar:
Dokümanlara bakın SSS: " Django'nun çalıştığı ham SQL sorgularını nasıl görebilirim? "
django.db.connection.queries
SQL sorgularının bir listesini içerir:
from django.db import connection
print(connection.queries)
Querysets ayrıca yürütülecek sorguyu içeren bir query
özniteliğe sahiptir :
print(MyModel.objects.filter(name="my name").query)
Sorgu çıktısının geçerli SQL olmadığını unutmayın, çünkü:
"Django asla parametreleri enterpolasyon etmez: sorguyu ve parametreleri ayrı ayrı, uygun işlemleri gerçekleştiren veritabanı bağdaştırıcısına gönderir."
Django hata raporundan # 17741 .
Bu nedenle, sorgu çıktısını doğrudan bir veritabanına göndermemelisiniz.
str()
dahili __str__()
yöntemi çağıran belirtilen yerleşik Pythonian işlevinin kullanılması önerilir . Örneğin str(MyModel.objects.filter(name="my name").query)
, IPython ve projenizin Django kabuğunu kullanmanızı tavsiye ederim. Sekme tamamlandığında nesne içgözlemi sağlanır. Django, iddialı adlandırma şemalarıyla tanındığı için, bu metodoloji çok yararlı olma eğilimindedir.
query
geçerli bir SQL çünkü değil "Django gerçekte hiçbir zaman parametreleri interpolates. Uygun işlemleri gerçekleştirir veritabanı adaptörü, ayrı ayrı sorgu ve parametreleri gönderir" Kaynak: code.djangoproject.com/ticket/17741
stable
değil dev
: Böyle Django şu anki sürümü olan ve bağlantıya, docs.djangoproject.com/en/stable/faq/models/...
Django uzantılarının bir parametresi olan shell_plus komutu varprint-sql
./manage.py shell_plus --print-sql
Django kabuğunda yürütülen tüm sorgular yazdırılır
Ör .:
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'a bir bakın, hata ayıklama için çok kullanışlıdır.
Dokümantasyon ve kaynak http://django-debug-toolbar.readthedocs.io/ adresinde bulunabilir .
q = Query.objects.values('val1','val2','val_etc')
print q.query
m = MyModel.objects.get(...)
takip ettiğimde işe yaramıyorm.query
m
artık bir sorgu kümesi değil. Kullan q = MyModel.objects.filter(...)
, sonra q.query
, sonra m = q.get()
.
Başka hiçbir yanıt bu yöntemi kapsamaz, bu nedenle:
Açık ara en yararlı, basit ve güvenilir yöntemi veri tabanınıza sormaktır. Örneğin Postgres için Linux'ta şunları yapabilirsiniz:
sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Her veritabanı biraz farklı prosedürlere sahip olacaktır. Veritabanı günlüklerinde yalnızca ham SQL'i görmezsiniz, ancak herhangi bir bağlantı kurulumu veya işlem yükü django sisteme yerleştirilir.
log_statement='all'
yılında postgresql.conf
bu yöntem için.
postgresql.conf
çalıştırarakpsql -U postgres -c 'SHOW config_file'
Sağlanan kod ile yapabilirsiniz, ancak hata ayıklama araç çubuğu uygulamasını kullanarak sorguları göstermek için harika bir araç olduğunu bulmak. Github'dan indirebilirsiniz buradan .
Bu, belirli bir sayfada çalıştırılan tüm sorguları sorgulama süresi ile birlikte gösterme seçeneği sunar. Ayrıca, hızlı bir inceleme için toplam süreyle birlikte bir sayfadaki sorguların sayısını da özetler. Bu, Django ORM'in perde arkasında ne yaptığını görmek istediğinizde harika bir araçtır. İsterseniz kullanabileceğiniz diğer birçok güzel özelliğe de sahiptir.
Başka bir seçenek, bu gönderi tarafından açıklanan settings.py'deki günlük seçeneklerine bakın.
http://dabapps.com/blog/logging-sql-queries-django-13/
debug_toolbar geliştirici sunucunuzdaki her sayfa yükünü yavaşlatır, günlüğe kaydetme daha hızlı olmaz. Çıktılar konsol veya dosyaya dökülebilir, böylece kullanıcı arayüzü o kadar hoş değildir. Ancak çok sayıda SQL içeren görünümler için, her sayfa yükü çok yavaş olduğundan SQL'lerin hata ayıklaması ve debug_toolbar aracılığıyla optimize edilmesi uzun sürebilir.
Settings.py dosyanızın şunlardan emin olduğundan emin olun:
django.core.context_processors.debug
listelenen CONTEXT_PROCESSORS
DEBUG=True
IP
içinde INTERNAL_IPS
tupleO zaman sql_queries
değişkene erişiminiz olmalıdır . Her sayfaya aşağıdaki gibi bir altbilgi ekliyorum:
{%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 %}
Değişkeni sql_time_sum
satır ekleyerek aldım
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
django_src / django / core / context_processors.py içindeki hata ayıklama işlevine
Bu amaçla bir uzantı geliştirdim, böylece görünüm işlevinize kolayca bir dekoratör koyabilir ve kaç sorgunun yürütüldüğünü görebilirsiniz.
Yüklemek:
$ pip install django-print-sql
İçerik yöneticisi olarak kullanmak için:
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()
Dekoratör olarak kullanmak için:
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 kullanıyorsanız bunun çalışması gerektiğine inanıyorum:
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())}')
Aşağıdaki sorgu, https://code.djangoproject.com/ticket/17741'e dayalı olarak sorguyu geçerli SQL olarak döndürür :
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 '):]
Kullanabileceğiniz küçük bir pasaj yaptım:
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)
İncelemek için parametre işlevi (sql sorguları içerir) ve bu işlevi çağırmak için gerekli kwargs olarak alır. Sonuç olarak hangi işlevin döndürdüğünü döndürür ve SQL sorgularını bir konsolda yazdırır.
Bu işlevi projemdeki uygulamalardan birinde bir util dosyasına koydum:
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)))
Sonra, gerektiğinde, ben sadece onu almak ve gerekli herhangi bir bağlam (genellikle bir görünüm) denir, örneğin:
# ... 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
Bunu şablonun dışında yapmak güzeldir, çünkü API görünümleriniz varsa (genellikle Django Rest Framework), orada da geçerlidir.
Django 2.2 için:
Cevapların çoğu kullanırken bana pek yardımcı olmadı ./manage.py shell
. Sonunda cevabı buldum. Umarım bu birine yardımcı olur.
Tüm sorguları görüntülemek için:
from django.db import connection
connection.queries
Tek bir sorgunun sorgusunu görüntülemek için:
q=Query.objects.all()
q.query.__str__()
q.query
sadece nesneyi benim için gösteriyorum. Kullanılması __str__()
(String temsilini) tam sorgu sergiledi.
Django.db.connection.queries kullanarak Sorguları Görüntüleme
from django.db import connection
print(connection.queries)
QuerySet nesnesinde ham SQL sorgusuna erişme
qs = MyModel.objects.all()
print(qs.query)
Sadece eklemek için, django, gibi bir sorgu varsa:
MyModel.objects.all()
yapmak:
MyModel.objects.all().query.sql_with_params()
sql dizesini almak için