• 3.2
  • 5.0
  • 6.1
  • Версия документации: 3.1

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

Чтобы помочь вам понять и контролировать запросы, выдаваемые вашим кодом, Django предоставляет возможность установки функций-оболочек для выполнения запросов к базе данных. Например, оболочки могут подсчитывать запросы, измерять продолжительность запроса, регистрировать запросы или даже предотвращать выполнение запроса (например, чтобы гарантировать, что никакие запросы не выполняются при отрисовке шаблона с предварительно выбранными данными).

Обертки созданы по образцу middleware — они являются вызываемыми объектами, которые принимают другой вызываемый объект в качестве одного из своих аргументов. Они вызывают этот вызываемый объект для вызова (возможно, завернутого) запроса к базе данных, и могут делать с этим вызовом все, что хотят. Однако они создаются и устанавливаются пользовательским кодом и поэтому не нуждаются в отдельной фабрике, как это делается в промежуточном программном обеспечении.

Установка оболочки выполняется в диспетчере контекста, поэтому оболочки являются временными и специфичными для определенного потока вашего кода.

Как упоминалось выше, примером оболочки является блокировщик выполнения запросов. Это может выглядеть так:

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 — вызываемый объект, который должен быть вызван с остальными параметрами для выполнения запроса.

  • sqlstr, SQL-запрос, который будет отправлен в базу данных.

  • params — список/кортеж значений параметров для команды SQL или список/кортеж списков/кортежей, если обернутым вызовом является executemany().

  • many — логическое значение, указывающее, является ли в конечном итоге вызванным вызовом 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) и вернет возвращаемое значение этого вызова.

Back to Top