Spec-Zone.ru › Django 2.1

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

Новое в Django 2.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.time()
        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.time() - 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/2.1/topics/db/instrumentation/

Spec-Zone.ru

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