是否有一种方法可以在执行查询时显示Django正在运行的SQL ?
当前回答
看一下debug_toolbar,它对调试非常有用。
文档和源代码可以在http://django-debug-toolbar.readthedocs.io/上找到。
其他回答
下面基于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 '):]
另一个选项,请参阅本文中描述的settings.py中的日志记录选项
http://dabapps.com/blog/logging-sql-queries-django-13/
Debug_toolbar会降低开发服务器上每个页面的加载速度,而日志记录则不会,因此速度更快。输出可以转储到控制台或文件,所以UI不是很好。但是对于包含大量sql的视图,通过debug_toolbar调试和优化sql可能需要很长时间,因为每个页面加载都非常慢。
在django中,如果你有这样的查询:
MyModel.objects.all()
do:
MyModel.objects.all().query.sql_with_params()
or:
str(MyModel.objects.all().query)
来获取SQL字符串
这里已经有几个很好的答案了。
还有一种方法。
在测试中,这样做:
with self.assertNumQueries(3):
response = self.client.post(reverse('payments:pay_list'))
# or whatever
如果查询数量错误,则测试失败,并在控制台中打印所有原始SQL查询。
此外,此类测试有助于控制SQL查询的数量不会随着代码的更改而增加,并且数据库负载不会过多。
你可以使用连接。在Django中运行原始SQL查询,如下所示:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.db import connection
from django.http import HttpResponse
@transaction.atomic
def test(request):
Person.objects.create(name="John") # INSERT
qs = Person.objects.select_for_update().get(name="John") # SELECT FOR UPDATE
qs.name = "Tom"
qs.save() # UPDATE
qs.delete() # DELETE
for query in connection.queries: # Here
print(query)
return HttpResponse("Test")
然后,原始查询打印在控制台,如下所示:
{'sql': 'INSERT INTO "store_person" ("name") VALUES (\'John\') RETURNING "store_person"."id"', 'time': '0.000'}
{'sql': 'SELECT "store_person"."id", "store_person"."name" FROM "store_person" WHERE "store_person"."name" = \'John\' LIMIT 21 FOR UPDATE', 'time': '0.000'}
{'sql': 'UPDATE "store_person" SET "name" = \'Tom\' WHERE "store_person"."id" = 179', 'time': '0.000'}
{'sql': 'DELETE FROM "store_person" WHERE "store_person"."id" IN (179)', 'time': '0.000'}
[24/Dec/2022 06:29:32] "GET /store/test/ HTTP/1.1" 200 9
然后,把reset_queries()放在Person.objects.select_for_update()之后,如果你想只得到UPDATE和DELETE查询,而没有INSERT和SELECT FOR UPDATE查询,如下所示:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.db import reset_queries
from django.db import connection
from django.http import HttpResponse
@transaction.atomic
def test(request):
Person.objects.create(name="John") # INSERT
qs = Person.objects.select_for_update().get(name="John") # SELECT FOR UPDATE
reset_queries() # Here
qs.name = "Tom"
qs.save() # UPDATE
qs.delete() # DELETE
for query in connection.queries: # Here
print(query)
return HttpResponse("Test")
然后,只打印UPDATE和DELETE查询,不打印INSERT和SELECT FOR UPDATE查询,如下所示:
{'sql': 'UPDATE "store_person" SET "name" = \'Tom\' WHERE "store_person"."id" = 190', 'time': '0.000'}
{'sql': 'DELETE FROM "store_person" WHERE "store_person"."id" IN (190)', 'time': '0.000'}
[24/Dec/2022 07:00:01] "GET /store/test/ HTTP/1.1" 200 9
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何在Ruby On Rails中使用NuoDB手动执行SQL命令
- 查询JSON类型内的数组元素
- 如何在django应用程序中显示favicon ?
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 确定记录是否存在的最快方法
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 获得PostgreSQL数据库中当前连接数的正确查询
- 如何创建类属性?