Инструментирование базы данных
Для помощи в понимании и управлении запросами, выполняемыми вашим кодом, 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) и вернёт значение этого вызова.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.1/topics/db/instrumentation/