# Django 5.2.8 documentation

# Instrumentering av databaser

För att hjälpa dig att förstå och kontrollera de frågor som utfärdas av din kod tillhandahåller Django en hook för att installera omslagsfunktioner runt exekveringen av databasfrågor. Till exempel kan wrappers räkna frågor, mäta frågans varaktighet, logga frågor eller till och med förhindra frågeexekvering (t.ex. för att se till att inga frågor utfärdas när du renderar en mall med förhämtade data).

Omslagen är modellerade efter middleware – de är anropsbara som tar en annan anropsbar som ett av sina argument. De anropar den anropsbara för att anropa databasfrågan (eventuellt inkapslad), och de kan göra vad de vill runt det anropet. De skapas och installeras dock av användarkoden och behöver därför inte en separat fabrik som middleware gör.

Installationen av en wrapper görs i en kontexthanterare - så wrappers är tillfälliga och specifika för ett visst flöde i din kod.

Som nämnts ovan är ett exempel på en wrapper en query execution blocker. Det skulle kunna se ut så här:

    def blocker(*args):
        raise Exception("No database access allowed here.")

Och det skulle användas i en vy för att blockera frågor från mallen så här:

    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)

De parametrar som skickas till wrappers är:

- `execute` – en anropsbar, som ska anropas med resten av parametrarna för att utföra frågan.

- `sql` – en `str`, SQL-frågan som ska skickas till databasen.

- `params` – en lista/tupel av parametervärden för SQL-kommandot, eller en lista/tupel av listor/tuplar om det omslutna anropet är `executemany()`.

- `many` – en `bool` som anger om det sista anropet är `execute()` eller `executemany()` (och om `params` förväntas vara en sekvens av värden, eller en sekvens av sekvenser av värden).

- `context` – en ordbok med ytterligare data om kontexten för anropet. Detta inkluderar anslutningen och markören.

Med hjälp av parametrarna kan en något mer komplex version av blockeraren inkludera anslutningsnamnet i felmeddelandet:

    def blocker(execute, sql, params, many, context):
        alias = context["connection"].alias
        raise Exception("Access to database '{}' blocked here".format(alias))

För ett mer komplett exempel kan en frågeloggare se ut så här:

    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)

För att använda detta skapar du ett logger-objekt och installerar det som en wrapper:

    from django.db import connection

    ql = QueryLogger()
    with connection.execute_wrapper(ql):
        do_queries()
    # Now we can print the log.
    print(ql.queries)

## `anslutning.execute_wrapper()`

execute_wrapper(wrapper)

Returnerar en kontexthanterare som, när den anges, installerar en omslagsdel runt exekveringar av databasfrågor, och när den avslutas, tar bort omslagsdelen. Omslaget installeras på det trådlokala anslutningsobjektet.

`wrapper` is a callable taking five arguments. It is called for every query execution in the scope of the context manager, with arguments `execute`, `sql`, `params`, `many`, and `context` as described above. It’s expected to call `execute(sql, params, many, context)` and return the return value of that call.