获取django orm query执行的的sql语句

摘要: 利用Django orM 可以很方便的写出很多查询,但有时候,我们需要检查这些利用 orM 生成的 SQL 语句是否正确,就需要检查这些ORM 生成的 原生的SQL 语句是否正确。经过测试有如下几种方法

利用Django orM 可以很方便的写出很多查询,但有时候,我们需要检查这些利用 orM 生成的 SQL 语句是否正确,就需要检查这些ORM 生成的 原生的SQL 语句是否正确。经过测试有如下几种方法:

1. 通过数据库的跟踪日志,可以看到查询的语句,比如mysql 就可以配置把所有的 SQL 语句打印到日志中,但这种方式并不推荐,只是没有办法的时候才这么做。

2. 利用django Query 提供的方法. 比如:

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


我采用pydev 对 django 进行debug, 如下是截图,可以清楚的看到结果:


3. 设置settings 里的 debug=True, 这个时候可以用这种方式来获取
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 '}]

4. 利用三方提供的middleware 来实现,参考这里: 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


当然,定义了这个middleware之后,需要修改setting 里的配置
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 语句, 推荐采用这种方式打印 sql 语句,因为比较方便,而且是插拔式的,不需要的时候去掉这个middleware就可以了,不过这只能在debug 模式下使用,对开发者来说足够了,生产环境不需要debug模式。

上一篇: spring security 教程入门
下一篇: 写sql语句时应注意的事项
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号