Spec-Zone.ru › Django 6.0

Инструментирование базы данных

Чтобы помочь вам понять и контролировать запросы, выполняемые вашим кодом, 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/6.0/topics/db/instrumentation/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API