数据库检测 — Django 文档
来自菜鸟教程
Django/docs/3.2.x/topics/db/instrumentation
数据库检测
为了帮助您理解和控制代码发出的查询,Django 提供了一个钩子,用于安装围绕数据库查询执行的包装函数。 例如,包装器可以对查询进行计数、测量查询持续时间、记录查询,甚至阻止查询执行(例如 以确保在渲染具有预取数据的模板时不会发出任何查询)。
包装器以 中间件 为模型——它们是可调用对象,它们将另一个可调用对象作为其参数之一。 他们调用可调用对象来调用(可能包装的)数据库查询,并且他们可以围绕该调用做他们想做的事情。 然而,它们是由用户代码创建和安装的,因此不需要像中间件那样的单独工厂。
安装包装器是在上下文管理器中完成的——因此包装器是临时的,并且特定于代码中的某些流程。
如上所述,包装器的一个示例是查询执行阻止程序。 它可能看起来像这样:
def blocker(*args):
raise Exception('No database access allowed here.')
它将在视图中用于阻止来自模板的查询,如下所示:
from django.db import connection
from django.shortcuts import render
def my_view(request):
context = {...} # Code to generate context with all data.
template_name = ...
with connection.execute_wrapper(blocker):
return render(request, template_name, context)
发送到包装器的参数是:
execute
– 一个可调用对象,应与其余参数一起调用以执行查询。sql
– 一个str
,要发送到数据库的 SQL 查询。params
– SQL 命令的参数值列表/元组,如果包装调用为executemany()
,则为列表/元组列表/元组。many
–bool
指示最终调用的调用是execute()
还是executemany()
(以及params
是否预期为值,或值序列的序列)。context
– 包含有关调用上下文的更多数据的字典。 这包括连接和游标。
使用这些参数,稍微复杂的阻止程序版本可能会在错误消息中包含连接名称:
def blocker(execute, sql, params, many, context):
alias = context['connection'].alias
raise Exception("Access to database '{}' blocked here".format(alias))
对于更完整的示例,查询记录器可能如下所示:
import time
class QueryLogger:
def __init__(self):
self.queries = []
def __call__(self, execute, sql, params, many, context):
current_query = {'sql': sql, 'params': params, 'many': many}
start = time.monotonic()
try:
result = execute(sql, params, many, context)
except Exception as e:
current_query['status'] = 'error'
current_query['exception'] = e
raise
else:
current_query['status'] = 'ok'
return result
finally:
duration = time.monotonic() - start
current_query['duration'] = duration
self.queries.append(current_query)
要使用它,您需要创建一个记录器对象并将其安装为包装器:
from django.db import connection
ql = QueryLogger()
with connection.execute_wrapper(ql):
do_queries()
# Now we can print the log.
print(ql.queries)
connection.execute_wrapper()
- execute_wrapper(wrapper)
返回一个上下文管理器,当进入时,它会在数据库查询执行周围安装一个包装器,并在退出时移除包装器。 包装器安装在线程本地连接对象上。
wrapper
是一个带有五个参数的可调用对象。 上下文管理器范围内的每个查询执行都会调用它,参数为 execute
、sql
、params
、many
和 [ X143X]如上所述。 预计调用 execute(sql, params, many, context)
并返回该调用的返回值。