获取Django框架ORM查询执行的SQL语句实现方法分析

周末不加班
周末不加班
发布时间:2026-10-13 | 5人浏览过
原创

本文详细解析了在Django框架中获取ORM生成的原生SQL语句的五种方法。包括通过数据库日志、Query对象属性、DEBUG模式配置、第三方中间件以及查看connections查询记录等方式。重点推荐了基于中间件的插拔式方案,适用于开发调试阶段,帮助开发者验证查询效率与正确性。

Django ORM SQL语句获取方法概述

本文详细介绍在Django框架中获取ORM查询所执行SQL语句的具体实现方法,供读者参考学习。

使用Django ORM可以便捷地构建各类数据查询,但在实际开发中,有时需要验证生成的SQL语句是否符合预期。为此,本文总结了以下几种有效的检查方式。

通过数据库日志查看

第一种方法是通过数据库的跟踪日志查看查询语句。例如,MySQL支持配置将SQL语句打印到日志中。不过,这种方式通常不被推荐,仅在无法使用其他手段时作为备选方案。

利用Query对象方法

第二种方法是利用Django Query对象提供的方法。具体操作示例如下:


 queryset = MyModel.objects.all()
 print 'query sql: ' + str(queryset .query)
 #result:

在PyDev环境中对Django进行调试时,可以通过截图直观地查看执行结果,确保查询逻辑正确。

配置DEBUG模式获取

第三种方法是修改settings配置中的 debug=True 参数。开启该设置后,可以通过特定方式获取执行的SQL语句。


from django.db import connections
connections['default'].queries

获取的结果格式通常如下所示:

[{u'time': u'0.000', u'sql': u'Select COUNT(*) FROM `my_article` Where `my_article`.`category` = 68 '}]

使用第三方中间件

第四种方法是使用第三方提供的中间件来实现SQL打印功能,具体参考链接:https://djangosnippets.org/snippets/290/。


from django.db import connection
from django.conf import settings
import os
def terminal_width():
  """
  Function to compute the terminal width.
  WARNING: This is not my code, but I've been using it forever and
  I don't remember where it came from.
  """
  width = 0
  try:
    import struct, fcntl, termios
    s = struct.pack('HHHH', 0, 0, 0, 0)
    x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
    width = struct.unpack('HHHH', x)[1]
  except:
    pass
  if width <= 0:
    try:
      width = int(os.environ['COLUMNS'])
    except:
      pass
  if width <= 0:
    width = 80
  return width
class SqlPrintingMiddleware(object):
  """
  Middleware which prints out a list of all SQL queries done
  for each view that is processed. This is only useful for debugging.
  """
  def process_response(self, request, response):
    indentation = 2
    if len(connection.queries) > 0 and settings.DEBUG:
      width = terminal_width()
      total_time = 0.0
      for query in connection.queries:
        nice_sql = query['sql'].replace('"', '').replace(',',', ')
        sql = "\033[1;31m[%s]\033[0m %s" % (query['time'], nice_sql)
        total_time = total_time + float(query['time'])
        while len(sql) > width-indentation:
          print "%s%s" % (" "*indentation, sql[:width-indentation])
          sql = sql[width-indentation:]
        print "%s%s\n" % (" "*indentation, sql)
      replace_tuple = (" "*indentation, str(total_time))
      print "%s\033[1;32m[TOTAL TIME: %s seconds]\033[0m" % replace_tuple
    return response

在定义好该中间件后,需要在settings中进行相应的配置以启用它。


MIDDLEWARE_CLASSES = (
  'django.middleware.common.CommonMiddleware',
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'yihaomen.common.mymiddleware.SqlPrintingMiddleware', # 这是增加的显示sql语句的middleware
  # Uncomment the next line for simple clickjacking protection:
  # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

配置完成后,系统会打印所有执行的SQL语句。这种方式被推荐用于开发环境,因为它具有插拔式特性,无需时可直接移除中间件。需要注意的是,该方案仅适用于Debug模式,对开发者而言已足够使用,生产环境通常无需开启。

希望本文所述内容能帮助读者更好地掌握Django框架下的Python程序设计技巧。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表