W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
為了幫助你更好的理解并控制由你的代碼所產(chǎn)生的數(shù)據(jù)庫(kù)查詢,Django提供了一個(gè)鉤子函數(shù),在這個(gè)鉤子函數(shù)中你可以在數(shù)據(jù)庫(kù)查詢方法外層添加一層?wrappers
?方法。 ?wrappers
?方法可以記錄數(shù)據(jù)庫(kù)查詢的數(shù)量, 計(jì)算查詢持續(xù)的事件, 為查詢記錄日志, 甚至可以阻止查詢的執(zhí)行(例如在渲染使用了預(yù)取的數(shù)據(jù)的模板時(shí)確保沒(méi)有數(shù)據(jù)庫(kù)查詢被執(zhí)行).
裝飾器是在 ?middleware
?之后建模的--它們是可調(diào)用的,并把其他調(diào)用作為它們的參數(shù)之一。它們調(diào)用可調(diào)用函數(shù)來(lái)調(diào)用(可能是包裝的)數(shù)據(jù)庫(kù)查詢,并且它們可以圍繞這個(gè)調(diào)用做一些工作。然而,它們通過(guò)用戶代碼來(lái)創(chuàng)建和安裝,因此不需要獨(dú)立像中間件這樣的獨(dú)立文件。
wrapper
?方法的安裝是在上下文管理器中完成的 -- 因此?wrapper
?方法是暫時(shí)的, 也是針對(duì)于你代碼里的某些特定邏輯的.
正如上面提到的, 一個(gè)使用?wrapper
?方法的例子是阻塞查詢的執(zhí)行. 類似的代碼為:
def blocker(*args):
raise Exception('No database access allowed here.')
它可以被用在視圖里阻止來(lái)自模板的查詢,如下所示:
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)
發(fā)給wrapper方法的參數(shù)是:
execute
?-- 一個(gè)可以被執(zhí)行的對(duì)象, 使用剩下的參數(shù)觸發(fā)來(lái)執(zhí)行查詢。sql
?-- 一個(gè) ?str
?,要發(fā)送到數(shù)據(jù)庫(kù)的SQL 查詢。params
?-- SQL命令行參數(shù)值的列表/二元組,或者列表集/二元組集的一個(gè)列表/二元組(如果包裝過(guò)的調(diào)用是 ?executemany()
? 的話)。many
?-- 一個(gè)布爾值,標(biāo)識(shí)最終的調(diào)用是否是 ?execute()
? 還是 ?executemany()
? (以及 ?params
?是否是一個(gè)值序列,還是一系列值的序列)。context
?-- 一個(gè)字典,包含帶有關(guān)于調(diào)用上下文的數(shù)據(jù)。使用這個(gè)參數(shù),稍微復(fù)雜一點(diǎn)的阻塞函數(shù)包含在錯(cuò)誤信息中的連接名:
def blocker(execute, sql, params, many, context):
alias = context['connection'].alias
raise Exception("Access to database '{}' blocked here".format(alias))
有關(guān)更完整的例子,一個(gè)查詢?nèi)罩酒骺雌饋?lái)像這樣:
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)
要使用它,你可以創(chuàng)建一個(gè)日志器對(duì)象,并且將其作為裝飾器來(lái)安裝:
from django.db import connection
ql = QueryLogger()
with connection.execute_wrapper(ql):
do_queries()
# Now we can print the log.
print(ql.queries)
返回一個(gè)上下文管理器,當(dāng)進(jìn)入時(shí),會(huì)安裝一個(gè)圍繞數(shù)據(jù)庫(kù)查詢執(zhí)行的裝飾器,當(dāng)離開(kāi)時(shí),會(huì)移除這個(gè)裝飾器。裝飾器是在本地線程的連接對(duì)象上安裝的。
wrapper 是一個(gè)帶有五個(gè)參數(shù)的可調(diào)用函數(shù)。它在上下文管理器的范圍內(nèi)被每個(gè)查詢調(diào)用,帶著上面所述的五個(gè)參數(shù) ?execute
?, ?sql
?, ?params
?, ?many
?,?context
?。它預(yù)計(jì)會(huì)調(diào)用 ?execute(sql, params, many, context)
?,并且返回那個(gè)調(diào)用的返回值。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: