99re热视频这里只精品,久久久天堂国产精品女人,国产av一区二区三区,久久久精品成人免费看片,99久久精品免费看国产一区二区三区

Django4.0 模型和數(shù)據(jù)庫-數(shù)據(jù)庫工具

2022-03-16 18:01 更新

為了幫助你更好的理解并控制由你的代碼所產(chǎn)生的數(shù)據(jù)庫查詢,Django提供了一個鉤子函數(shù),在這個鉤子函數(shù)中你可以在數(shù)據(jù)庫查詢方法外層添加一層?wrappers?方法。 ?wrappers?方法可以記錄數(shù)據(jù)庫查詢的數(shù)量, 計算查詢持續(xù)的事件, 為查詢記錄日志, 甚至可以阻止查詢的執(zhí)行(例如在渲染使用了預(yù)取的數(shù)據(jù)的模板時確保沒有數(shù)據(jù)庫查詢被執(zhí)行).

裝飾器是在 ?middleware ?之后建模的--它們是可調(diào)用的,并把其他調(diào)用作為它們的參數(shù)之一。它們調(diào)用可調(diào)用函數(shù)來調(diào)用(可能是包裝的)數(shù)據(jù)庫查詢,并且它們可以圍繞這個調(diào)用做一些工作。然而,它們通過用戶代碼來創(chuàng)建和安裝,因此不需要獨立像中間件這樣的獨立文件。

wrapper?方法的安裝是在上下文管理器中完成的 -- 因此?wrapper?方法是暫時的, 也是針對于你代碼里的某些特定邏輯的.

正如上面提到的, 一個使用?wrapper?方法的例子是阻塞查詢的執(zhí)行. 類似的代碼為:

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)

發(fā)給wrapper方法的參數(shù)是:

  • ?execute ?-- 一個可以被執(zhí)行的對象, 使用剩下的參數(shù)觸發(fā)來執(zhí)行查詢。
  • ?sql ?-- 一個 ?str?,要發(fā)送到數(shù)據(jù)庫的SQL 查詢。
  • ?params ?-- SQL命令行參數(shù)值的列表/二元組,或者列表集/二元組集的一個列表/二元組(如果包裝過的調(diào)用是 ?executemany()? 的話)。
  • ?many ?-- 一個布爾值,標(biāo)識最終的調(diào)用是否是 ?execute()? 還是 ?executemany()? (以及 ?params ?是否是一個值序列,還是一系列值的序列)。
  • ?context ?-- 一個字典,包含帶有關(guān)于調(diào)用上下文的數(shù)據(jù)。

使用這個參數(shù),稍微復(fù)雜一點的阻塞函數(shù)包含在錯誤信息中的連接名:

def blocker(execute, sql, params, many, context):
    alias = context['connection'].alias
    raise Exception("Access to database '{}' blocked here".format(alias))

有關(guān)更完整的例子,一個查詢?nè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)建一個日志器對象,并且將其作為裝飾器來安裝:

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)

返回一個上下文管理器,當(dāng)進(jìn)入時,會安裝一個圍繞數(shù)據(jù)庫查詢執(zhí)行的裝飾器,當(dāng)離開時,會移除這個裝飾器。裝飾器是在本地線程的連接對象上安裝的。
wrapper 是一個帶有五個參數(shù)的可調(diào)用函數(shù)。它在上下文管理器的范圍內(nèi)被每個查詢調(diào)用,帶著上面所述的五個參數(shù) ?execute?, ?sql?, ?params?, ?many?,?context ?。它預(yù)計會調(diào)用 ?execute(sql, params, many, context) ?,并且返回那個調(diào)用的返回值。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號