django - 每个执行的 sql 语句的信号/方法
问题描述
根据这个 12 年的问题,django 不支持每个执行的 sql 语句的信号:https ://code.djangoproject.com/ticket/5415
我在调试 = False 的生产环境中需要这个。
这意味着覆盖 connection.queries 不起作用。
有没有办法在每个 sql 语句之后运行一些自定义代码(即使 debug=False)?
解决方案
我已经查看了 Django 的填充方式connection.queries
。当 时DEBUG = True
,所有后端使用的基本数据库后端代码用 包装特定于数据库的游标CursorDebugWrapper
。否则,它使用CursorWrapper
. 理论上,即使DEBUG = False
通过覆盖属性或在数据库连接对象上queries_logged
设置标志,也可以强制 Django 填充它。force_debug_cursor
任何一种方法都会强制 Django 使用,CursorDebugWrapper
即使DEBUG
是False
. 但是,我不推荐这种方法,因为CursorDebugWrapper
在您只想知道查询已执行的情况下,这种方法并不是特别有效。例如,除了填充connection.queries
它之外,它还会将查询记录到记录器中。如果您不需要此日志记录,那么这只是一种浪费。
因此,从工作原理中汲取灵感CursorDebugWrapper
,我想出了一种自定义方法来了解何时进行了 SQL 查询。
我创建了一个应用程序first
,名为__init__.py
:
from django.db.backends import utils
from contextlib import contextmanager
# This is inspired by Django's stock CursorDebugWrapper class.
class Mixin(object):
def execute(self, sql, params=None):
with self.notify(sql, params, use_last_executed_query=True):
return super().execute(sql, params)
def executemany(self, sql, param_list):
with self.notify(sql, param_list):
return super().executemany(sql, param_list)
@contextmanager
def notify(self, sql=None, params=None, use_last_executed_query=False):
try:
yield
finally:
if use_last_executed_query:
sql = self.db.ops.last_executed_query(self.cursor, sql, params)
# I've used print for this proof-of-concept, replace with whatever
# mechanism suits you.
print("Executed: ", sql)
class CustomWrapper(Mixin, utils.CursorWrapper):
pass
class CustomDebugWrapper(Mixin, utils.CursorDebugWrapper):
pass
utils.CursorWrapper = CustomWrapper
utils.CursorDebugWrapper = CustomDebugWrapper
然后在我的settings.py
文件中,我将first
应用程序放在首位INSTALLED_APPS
。这使得它的__init__.py
文件在访问数据库的任何内容之前执行。
这实际上是用允许知道 SQL 查询何时发生的自定义类替换库存CursorWrapper
和类。CursorDebugWrapper
此更改对 Django 附带的所有后端生效。
我不知道另一种方法可以像我在上面所做的那样一举添加此功能。我首先查看是否可以从现有后端派生新后端。我确信这是可行的,但它需要大量的样板文件。此外,一次使用多个后端的项目必须为最初使用的每个库存后端派生一个新的后端。
推荐阅读
- c - 混淆为什么程序输出不正确问题是检查整数是否是阿姆斯壮数
- html - 如何在 div 容器之外对齐我的图像?
- php - touch(): Utime failed: 不允许操作
- python - 如何让python在下载文件时点击弹出按钮自动打开文件?
- regex - 环顾内的多个正则表达式匹配
- python-3.x - 循环遍历 PuLP 嵌套变量以获取特定约束
- sql - 返回表数据类型的 T-SQL 函数。想遍历这张表
- javascript - vercel 上是否有“now dev”的替代命令?
- angularjs - AngularJS highcharts 点击事件
- java - 如何在终端上正确打印月历