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

Чтобы помочь вам понять и контролировать запросы, выдаваемые вашим кодом, 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- a 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вызывается с пятью аргументами. Она вызывается для каждого выполнения запроса в рамках менеджера контекста, с аргументами execute, sql, params, many, и , contextкак описано выше. Ожидается, что он вызовет и вернет возвращаемое значение этого вызова.execute(sql, params, many, context)

Copyright ©2021 All rights reserved