是否有一种方法可以在执行查询时显示Django正在运行的SQL ?
当前回答
我为此开发了一个扩展,所以你可以很容易地在你的视图函数上放一个装饰器,看看有多少查询被执行了。
如何安装:
$ 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
其他回答
请参阅文档常见问题:“如何查看Django正在运行的原始SQL查询?”
django.db.connection.queries包含一个SQL查询列表:
from django.db import connection
print(connection.queries)
queryset也有一个包含要执行的查询的query属性:
print(MyModel.objects.filter(name="my name").query)
注意,查询的输出不是有效的SQL,因为:
Django从未真正插入参数:它将查询和参数分别发送到数据库适配器,由数据库适配器执行适当的操作。
来自Django错误报告#17741。
因此,不应该将查询输出直接发送到数据库。
如果你需要重置查询,例如,查看在给定的时间内有多少查询在运行,你可以使用reset_queries from django.db:
from django.db import reset_queries
from django.db import connection
reset_queries()
# Run your query here
print(connection.queries)
>>> []
从django获取查询结果到数据库(使用正确的参数替换) 你可以使用这个函数:
from django.db import connection
def print_database_query_formatted(query):
sql, params = query.sql_with_params()
cursor = connection.cursor()
cursor.execute('EXPLAIN ' + sql, params)
db_query = cursor.db.ops.last_executed_query(cursor, sql, params).replace('EXPLAIN ', '')
parts = '{}'.format(db_query).split('FROM')
print(parts[0])
if len(parts) > 1:
parts = parts[1].split('WHERE')
print('FROM{}'.format(parts[0]))
if len(parts) > 1:
parts = parts[1].split('ORDER BY')
print('WHERE{}'.format(parts[0]))
if len(parts) > 1:
print('ORDER BY{}'.format(parts[1]))
# USAGE
users = User.objects.filter(email='admin@admin.com').order_by('-id')
print_database_query_formatted(users.query)
输出示例
SELECT "users_user"."password", "users_user"."last_login", "users_user"."is_superuser", "users_user"."deleted", "users_user"."id", "users_user"."phone", "users_user"."username", "users_user"."userlastname", "users_user"."email", "users_user"."is_staff", "users_user"."is_active", "users_user"."date_joined", "users_user"."latitude", "users_user"."longitude", "users_user"."point"::bytea, "users_user"."default_search_radius", "users_user"."notifications", "users_user"."admin_theme", "users_user"."address", "users_user"."is_notify_when_buildings_in_radius", "users_user"."active_campaign_id", "users_user"."is_unsubscribed", "users_user"."sf_contact_id", "users_user"."is_agree_terms_of_service", "users_user"."is_facebook_signup", "users_user"."type_signup"
FROM "users_user"
WHERE "users_user"."email" = 'admin@admin.com'
ORDER BY "users_user"."id" DESC
它基于这个票证评论:https://code.djangoproject.com/ticket/17741#comment:4
另一个选项,请参阅本文中描述的settings.py中的日志记录选项
http://dabapps.com/blog/logging-sql-queries-django-13/
Debug_toolbar会降低开发服务器上每个页面的加载速度,而日志记录则不会,因此速度更快。输出可以转储到控制台或文件,所以UI不是很好。但是对于包含大量sql的视图,通过debug_toolbar调试和优化sql可能需要很长时间,因为每个页面加载都非常慢。
使用django.db.connection.queries查看查询
from django.db import connection
print(connection.queries)
访问QuerySet对象上的原始SQL查询
qs = MyModel.objects.all()
print(qs.query)
为CREATE / UPDATE / DELETE /命令生成SQL,这在Django中是即时的
from django.db.models import sql
def generate_update_sql(queryset, update_kwargs):
"""Converts queryset with update_kwargs
like : queryset.update(**update_kwargs) to UPDATE SQL"""
query = queryset.query.clone(sql.UpdateQuery)
query.add_update_values(update_kwargs)
compiler = query.get_compiler(queryset.db)
sql, params = compiler.as_sql()
return sql % params
from django.db.models import sql
def generate_delete_sql(queryset):
"""Converts select queryset to DELETE SQL """
query = queryset.query.chain(sql.DeleteQuery)
compiler = query.get_compiler(queryset.db)
sql, params = compiler.as_sql()
return sql % params
from django.db.models import sql
def generate_create_sql(model, model_data):
"""Converts queryset with create_kwargs
like if was: queryset.create(**create_kwargs) to SQL CREATE"""
not_saved_instance = model(**model_data)
not_saved_instance._for_write = True
query = sql.InsertQuery(model)
fields = [f for f in model._meta.local_concrete_fields if not isinstance(f, AutoField)]
query.insert_values(fields, [not_saved_instance], raw=False)
compiler = query.get_compiler(model.objects.db)
sql, params = compiler.as_sql()[0]
return sql % params
测试和使用
def test_generate_update_sql_with_F(self):
qs = Event.objects.all()
update_kwargs = dict(description=F('slug'))
result = generate_update_sql(qs, update_kwargs)
sql = "UPDATE `api_event` SET `description` = `api_event`.`slug`"
self.assertEqual(sql, result)
def test_generate_create_sql(self):
result = generate_create_sql(Event, dict(slug='a', app='b', model='c', action='e'))
sql = "INSERT INTO `api_event` (`slug`, `app`, `model`, `action`, `action_type`, `description`) VALUES (a, b, c, e, , )"
self.assertEqual(sql, result)
推荐文章
- 获取对象的Django管理url
- 比较两个SQL Server数据库(模式和数据)的最佳工具是什么?
- 在SQL中,如何在范围中“分组”?
- 选项(RECOMPILE)总是更快;为什么?
- 如何制作好的可复制的熊猫例子
- 2个数字表的余弦相似度
- 如何从熊猫的两列形成元组列
- 如何读一个文本文件到一个列表或数组与Python
- 设置数据库从单用户模式到多用户
- Django可选url参数
- 在matplotlib上为散点图中的每个系列设置不同的颜色
- oracle中的RANK()和DENSE_RANK()函数有什么区别?
- 如何加载一个tsv文件到熊猫数据框架?
- 从csv文件创建字典?
- 我如何提高一个响应禁止在django