資料庫檢測¶
為了幫助您理解並控制您的程式碼所發出的查詢,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
和 context
,如上所述。它預期會呼叫 execute(sql, params, many, context)
並傳回該呼叫的傳回值。