Peralatan basisdata

Untuk membantu anda memahami dan mengendalikan permintaan dengan kode anda, Django menyediakan sebuah kaitan untuk memasang fungsi pembungkus disekitar penjalanan dari permintaan basisdata. Sebagai contoh, pembungkus dapat menghitung permintaan, mengukur lama permintaan, mencatat permintaan, atau bahkan mencegah penjalanan permintaan (sebagai contoh memastikan bahwa tidak ada permintaan diterbitkan selagi membangun cetakan dengan data pra pengambilan).

Pembungkus-pembungkus dimodelkan setelah middleware 1 -- mereka adalah callable yang mengambil callable lain sebagai argumen mereka. Mereka memanggil bahwa callable untuk meminta (kemungkinan dibungkus) permintaan basisdata, dan mereka dapat melakukan apa mereka ingin disekitaran panggilan itu. Mereka adalah, bagaimanapun, dibuat dan dipasang oleh kode pengguna, dan jadi tidak butuh memisahkan factory seperti middleware lakukan.

Memasang sebuah pembungkus selesai dalam sebuah pengelola konteks -- jadi pembungkus adalah sementara dan tertentu pada beberapa alur di kode anda.

Seperti disebutkan diatas, sebuah contoh dari sebuah pembungkus adalah penghadang penjalanan permintaan. Itu dapat terlihat seperti ini:

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

Dan itu akan digunakan dalam sebuah tampilan untuk menghadang permintaan dari cetakan seperti berikut:

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)

Parameter dikirim ke pembungkus adalah:

  • middleware 1 -- sebuah callable, yang harus diminta dengan sisa dari parameter untuk menjalankan permintaan.
  • sql -- sebuah str, permintaan SQL dikirim ke basisdata.
  • params -- sebuah list/tuple dari nilai-nilai parameter untuk perintah SQL, atau list/tuple dari list/tuple jika panggilan dibungkus adalah executemany().
  • many -- sebuah bool menunjukkan akhirnya panggilan dipangil adalah execute() atau executemany() (dan apakah params diharapkan menjadi berurut dari nilai-nilai, atau urutan dari urutan-urutan dari nilai-nilai).
  • context -- sebuah dictionary dengan data lebih lanjut tentang konteks dari permohonan. Ini menyertakan hubungan dan kursor.

Menggunakan parameter, versi sedikit lebih rumit dari penghadang dapat menyertakan nama hubungan dalam pesan kesalahan:

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

Untuk contoh lebih lengkap, sebuah pencatat permintaan dapat terlihat seperti ini:

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)

Untuk menggunakan ini, anda dapat membuat sebuah obyek pencatat dan memasang itu sebagai pembungkus:

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)

Mengembalikan pengeola konteks yang, ketika dimasukkan, memasang sebuah pembungkus disekitar penjalanan permintaan basisdata, dan ketika keluar, memindahkan pembungkus. Pembungkus dipasang pada obyek hubungan lokal-thread.

wrapper adalah sebuah callable mengambil lima argumen. Itu dipanggil untuk setiap penjalanan permintaan dalam cakupan dari pengelola konteks, dengan argumen execute, sql, params, many, dan context sebagai digambarkan diatas. Itu diharapkan memanggil execute(sql, params, many, context) dan mengembalikan nilai balikan dari panggilan itu.