为了帮助你更好的理解并控制由你的代码所产生的数据库查询,Django提供了一个钩子函数,在这个钩子函数中你可以在数据库查询方法外层添加一层wrappers
方法。 wrappers
方法可以记录数据库查询的数量, 计算查询持续的事件, 为查询记录日志, 甚至可以阻止查询的执行(例如在渲染使用了预取的数据的模板时确保没有数据库查询被执行).
装饰器是在 middleware
之后建模的--它们是可调用的,并把其他调用作为它们的参数之一。它们调用可调用函数来调用(可能是包装的)数据库查询,并且它们可以围绕这个调用做一些工作。然而,它们通过用户代码来创建和安装,因此不需要独立像中间件这样的独立文件。
wrapper
方法的安装是在上下文管理器中完成的 -- 因此wrapper
方法是暂时的, 也是针对于你代码里的某些特定逻辑的.
正如上面提到的, 一个使用wrapper
方法的例子是阻塞查询的执行. 类似的代码为:
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)
发给wrapper方法的参数是:
execute
-- 一个可以被执行的对象, 使用剩下的参数触发来执行查询。sql
-- 一个 str
,要发送到数据库的SQL 查询。params
-- SQL命令行参数值的列表/二元组,或者列表集/二元组集的一个列表/二元组(如果包装过的调用是 executemany()
的话)。many
-- 一个布尔值,标识最终的调用是否是 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)
返回一个上下文管理器,当进入时,会安装一个围绕数据库查询执行的装饰器,当离开时,会移除这个装饰器。装饰器是在本地线程的连接对象上安装的。
wrapper 是一个带有五个参数的可调用函数。它在上下文管理器的范围内被每个查询调用,带着上面所述的五个参数 execute
, sql
, params
, many
,context
。它预计会调用 execute(sql, params, many, context)
,并且返回那个调用的返回值。
网站栏目:创新互联Django4.0教程:Django4.0模型和数据库-数据库工具
文章分享:http://www.shufengxianlan.com/qtweb/news38/446188.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联