web-dev-qa-db-ja.com

生のSQLクエリDjangoが実行されていることを確認するにはどうすればよいですか?

クエリの実行中にDjangoが実行されているSQLを表示する方法はありますか?

247
spence91

ドキュメントのよくある質問をご覧ください: " 生の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

そのため、クエリ出力をデータベースに直接送信しないでください。

305
geowa4

debug_toolbarを見てください。デバッグに非常に役立ちます。

ドキュメントとソースは http://Django-debug-toolbar.readthedocs.io/ で入手できます。

Screenshot of debug toolbar

44
Glader

Django-extensions コマンドがあります Shell_plus パラメーターprint-sql

./manage.py Shell_plus --print-sql

Django-Shellでは、実行されたすべてのクエリが出力されます

例:

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>
40
Patrick Z
q = Query.objects.values('val1','val2','val_etc')

print q.query
17
jgabrielsk8

提供されたコードを使用してそれを行うことができますが、デバッグツールバーアプリを使用すると、クエリを表示するための優れたツールであることがわかります。 github here からダウンロードできます。

これにより、特定のページで実行されたすべてのクエリを、クエリにかかった時間とともに表示するオプションが提供されます。また、ページのクエリ数と合計時間を合計して、簡単に確認できるようにします。これは、Django ORMが舞台裏で行うことを確認したい場合に最適なツールです。また、他にも多くの素敵な機能があり、必要に応じて使用できます。

16
googletorp

この方法をカバーする答えは他にありません。

私が断然最も便利で、シンプルで、信頼できる方法は、データベースに尋ねることであると思います。たとえば、Postgres用のLinuxでは次のようにします。

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

各データベースの手順はわずかに異なります。データベースログには、生のSQLだけでなく、接続セットアップまたはトランザクションオーバーヘッドDjangoがシステムに配置されていることがわかります。

16
Bryce

別のオプション、この投稿で説明されているsettings.pyのロギングオプションを参照してください

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

debug_toolbarは、開発サーバーでの各ページの読み込みを遅くしますが、ロギングは遅くなりませんので、速くなります。出力はコンソールまたはファイルにダンプできるため、UIは見栄えがよくありません。ただし、SQLが多いビューの場合、各ページのロードが非常に遅いため、debug_toolbarを使用してSQLをデバッグおよび最適化するのに長い時間がかかる場合があります。

13
Overclocked

Settings.pyファイルに以下が含まれていることを確認した場合:

  1. Django.core.context_processors.debugCONTEXT_PROCESSORSにリストされています
  2. DEBUG=True
  3. INTERNAL_IPSタプルのIP

次に、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のデバッグ関数へ。

10
Mike Howsden

この目的で拡張機能を開発したので、ビュー関数にデコレーターを簡単に配置して、実行されたクエリの数を確認できます。

インストールする:

$ 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

5
rabbit.aaron

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

次は、 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 '):]
1
Flash

次の操作を行うだけで、失敗したクエリを確認できました。

tail -f /var/log/postgresql/*

これは、postgres 10.6、ubuntu 18.04 +、python3 +、Django2 +、およびロギングがpostgresで有効になっていることを前提としています。

0
jmunsch

使用できる小さなスニペットを作成しました:

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クエリをコンソールに出力します。

0
turkus