Django가 실행중인 원시 SQL 쿼리를 어떻게 볼 수 있습니까?


307

쿼리를 수행하는 동안 Django가 실행중인 SQL을 표시하는 방법이 있습니까?

답변:


372

docs FAQ : " Django가 실행중인 원시 SQL 쿼리를 어떻게 확인할 수 있습니까? "를 참조하십시오.

django.db.connection.queries SQL 쿼리 목록을 포함합니다.

from django.db import connection
print(connection.queries)

또한 쿼리 셋에는 실행할 쿼리가 포함 된 query속성 이 있습니다.

print(MyModel.objects.filter(name="my name").query)

다음과 같은 이유로 쿼리 출력이 유효한 SQL이 아닙니다.

"Django는 실제로 매개 변수를 보간하지 않습니다. 쿼리와 매개 변수를 개별적으로 데이터베이스 어댑터로 보내 적절한 작업을 수행합니다."

장고 버그 보고서 # 17741에서 .

따라서 쿼리 출력을 데이터베이스로 직접 보내면 안됩니다.



5
좋은 대답입니다. 그러나 str()내부 __str__()메소드 를 호출하는 지정된 내장 Pythonian 함수 를 사용하는 것이 좋습니다 . 예를 들어 str(MyModel.objects.filter(name="my name").query) 프로젝트의 IPython과 Django 셸을 사용하는 것이 좋습니다. 그런 다음 탭 완성은 객체 내부 검사를 제공합니다. Django는 독창적 인 이름 지정 체계로 유명하기 때문에이 방법은 매우 유용한 경향이 있습니다.
Lorenz Lo Sauer

7
query"Django는 실제로 매개 변수를 보간하지 않습니다. 쿼리와 매개 변수를 데이터베이스 어댑터에 별도로 전송하여 적절한 조작을 수행합니다." 라는 결과 는 유효한 SQL이 아닙니다. 출처 : code.djangoproject.com/ticket/17741
gregoltsov

3
@AndreMiller stable, not을 사용 dev하여 다음과 같이 Django의 현재 버전에 연결해야합니다. docs.djangoproject.com/en/stable/faq/models/…
Flimm

3
django.db.connection.queries는 빈리스트를 반환
fantastory

61

장고 확장 에는 매개 변수 가있는 shell_plus 명령이 있습니다.print-sql

./manage.py shell_plus --print-sql

장고 셸에서 실행 된 모든 쿼리가 인쇄됩니다.

전의.:

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>

1
--print-sql 또는 SHELL_PLUS_PRINT_SQL = True와 함께 사용하고 있는데 도움이되지 않습니다. 여전히 쿼리를 볼 수 없습니다. 왜 그런지 알아? django 1.8
Dejell

1
쿼리를 보려면 settings.py에서 DEBUG = True를 설정해야합니다.
Konstantin

50

debug_toolbar를 살펴보면 디버깅에 매우 유용합니다.

설명서 및 소스는 http://django-debug-toolbar.readthedocs.io/ 에서 수 있습니다 .

디버그 툴바 스크린 샷


1
debug_toolbar는 SQL 구문 오류로 인해 실패한 쿼리가있을 때 특히 유용합니다. 실행을 시도하고 실패한 마지막 쿼리를 표시하여 디버그하기가 더 쉽습니다.
scoopseven

브라우저에서 SQL 쿼리를 보는 것이 유일한 방법입니다. 터미널에서 테스트를 실행하고 테스트를 원한다면 이것이 가능한 해결책이 아닙니다. 여전히 큰 일이지만, 나는 오늘날까지 그것을 사용하고 있습니다.
Erdin Eray

24
q = Query.objects.values('val1','val2','val_etc')

print q.query

매우 간단한 답변! 니스
Espoir Murhabazi

이 기능이 제거 되었습니까? 내가 m = MyModel.objects.get(...)m.query
sg

m더 이상 쿼리 셋이 아니기 때문 입니다. q = MyModel.objects.filter(...),을 q.query차례로 사용합니다 m = q.get().
Brouwer

24

다른 방법으로는이 방법을 다루지 않으므로 다음을 수행하십시오.

가장 유용하고 간단하며 신뢰할 수있는 방법은 데이터베이스를 요청하는 것입니다. 예를 들어 Linux for Postgres에서 다음을 수행 할 수 있습니다.

sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log

각 데이터베이스마다 절차가 약간 다릅니다. 데이터베이스 로그에는 원시 SQL뿐만 아니라 모든 연결 설정 또는 트랜잭션 오버 헤드 django가 시스템에 있습니다.


8
설정하는 것을 잊지 마세요 log_statement='all'postgresql.conf이 방법을 위해.
RickyA

2
postgresql.confpsql -U postgres -c 'SHOW config_file'
kramer65

17

제공된 코드를 사용하여 수행 할 수 있지만 디버그 도구 모음 앱을 사용하는 것이 쿼리를 표시하는 훌륭한 도구라는 것을 알았습니다. 여기 에서 github 에서 다운로드 할 수 있습니다 .

이를 통해 주어진 페이지에서 실행 된 모든 쿼리를 쿼리 시간과 함께 표시 할 수 있습니다. 또한 빠른 검토를 위해 페이지의 쿼리 수와 총 시간을 합산합니다. Django ORM이 무대 뒤에서 무엇을하는지보고 싶을 때 훌륭한 도구입니다. 그것은 또한 당신이 원한다면 사용할 수있는 다른 좋은 기능이 많이 있습니다.


2
이것이 최고의 버전 인 것 같습니다 : github.com/django-debug-toolbar/django-debug-toolbar
philfreo

15

다른 옵션은 settings.py의 로깅 옵션을 참조하십시오.

http://dabapps.com/blog/logging-sql-queries-django-13/

debug_toolbar는 개발자 서버의 각 페이지로드 속도를 늦추므로 로깅 속도가 빠르지 않습니다. 출력은 콘솔이나 파일로 덤프 될 수 있으므로 UI가 좋지 않습니다. 그러나 SQL이 많은 뷰의 경우 각 페이지로드가 너무 느리기 때문에 debug_toolbar를 통해 SQL을 디버깅하고 최적화하는 데 시간이 오래 걸릴 수 있습니다.


우수한! 툴바는 훌륭해 보이지만이 답변이 받아 들여 져야한다고 생각합니다. 이것은 "manage.py runserver"가 SQL을 콘솔에 기록하고 "manage.py migrate"와 함께 작동하기 때문에 원하는 솔루션입니다. 후자는 테이블을 만들 때 "캐스케이드 삭제시"가 확실히 설정되지 않았다는 것을 알 수 있습니다. 이 답변은 docs.djangoproject.com/en/1.9/topics/logging/…을
LS

10

settings.py 파일에 다음이 있는지 확인하십시오.

  1. django.core.context_processors.debug 에 나열된 CONTEXT_PROCESSORS
  2. DEBUG=True
  3. 당신의 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의 디버그 기능에.


1
방금 이것을 시도하고 (sql_time_sum 부분을 제거했습니다), 템플릿에 명명 된 사이클이 없습니다. 'odd, even'이 정의되지 않았습니다. 무엇을 놓치고 있습니까?
버림받은

8

이 목적을 위해 확장 프로그램을 개발 했으므로 뷰 기능에 데코레이터를 쉽게 배치하고 얼마나 많은 쿼리가 실행되는지 확인할 수 있습니다.

설치하기 위해서:

$ 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

Github : https://github.com/rabbit-aaron/django-print-sql


3

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())}')

이것은 Python 2에서도 작동했습니다. print (cursor.mogrify (* qs.query.sql_with_params ()))와 같은 리 팩터 만 있으면됩니다.
iChux

IIRC Cursor.mogrify는 문자열을 반환하므로 형식화에 f 문자열을 사용하는 것이 불필요한 것으로 생각됩니다.
chander

2

다음은 https://code.djangoproject.com/ticket/17741을 기반으로 쿼리를 유효한 SQL로 반환합니다 .

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 '):]

2

사용할 수있는 작은 스 니펫을 만들었습니다.

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)

kwargs는 해당 함수를 호출하는 데 필요한 매개 변수 함수 (SQL 쿼리 포함)를 검사하고 인수합니다. 결과적으로 어떤 함수가 콘솔에서 SQL 쿼리를 반환하고 인쇄하는지 반환합니다.


1

이 기능을 내 프로젝트의 앱 중 하나에있는 util 파일에 넣었습니다.

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)가있는 경우에도 적용 할 수 있기 때문입니다.


1

Django 2.2의 경우 :

를 사용할 때 대부분의 답변이 저에게 도움이되지 않았기 때문에 ./manage.py shell. 마침내 나는 답을 찾았습니다. 이것이 누군가에게 도움이되기를 바랍니다.

모든 쿼리를 보려면

from django.db import connection
connection.queries

단일 쿼리에 대한 쿼리를 보려면

q=Query.objects.all()
q.query.__str__()

q.query나를 위해 객체를 표시합니다. __str__()(문자열 표현)을 사용하여 전체 쿼리를 표시했습니다.


0

django.db.connection.queries를 사용하여 쿼리보기

from django.db import connection
print(connection.queries)

QuerySet 오브젝트에서 원시 SQL 쿼리에 액세스

 qs = MyModel.objects.all()
 print(qs.query)

0

django에서 다음과 같은 쿼리가 있으면 추가하십시오.

MyModel.objects.all()

하다:

MyModel.objects.all().query.sql_with_params()

SQL 문자열을 얻으려면

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.