{"title":"Database instrumentation","version":"4.1","locale":"el","docname":"topics/db/instrumentation","url":"/el/4.1/topics/db/instrumentation/","canonical":"https://djangodocs.dev/el/4.1/topics/db/instrumentation/","summary":"To help you understand and control the queries issued by your code, Django provides a hook for installing wrapper functions around the execution of database…","html":"<h1>Database instrumentation<a class=\"heading-anchor\" href=\"#database-instrumentation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>To help you understand and control the queries issued by your code, Django\nprovides a hook for installing wrapper functions around the execution of\ndatabase queries. For example, wrappers can count queries, measure query\nduration, log queries, or even prevent query execution (e.g. to make sure that\nno queries are issued while rendering a template with prefetched data).</p>\n<p>The wrappers are modeled after <a class=\"reference internal\" href=\"/el/4.1/topics/http/middleware/\"><span class=\"doc\">middleware</span></a> –\nthey are callables which take another callable as one of their arguments. They\ncall that callable to invoke the (possibly wrapped) database query, and they\ncan do what they want around that call. They are, however, created and\ninstalled by user code, and so don’t need a separate factory like middleware do.</p>\n<p>Installing a wrapper is done in a context manager – so the wrappers are\ntemporary and specific to some flow in your code.</p>\n<p>As mentioned above, an example of a wrapper is a query execution blocker. It\ncould look like this:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">blocker</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">):</span>\n    <span class=\"k\">raise</span> <span class=\"ne\">Exception</span><span class=\"p\">(</span><span class=\"s1\">&#39;No database access allowed here.&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>And it would be used in a view to block queries from the template like so:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">connection</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"o\">...</span><span class=\"p\">}</span>  <span class=\"c1\"># Code to generate context with all data.</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"o\">...</span>\n    <span class=\"k\">with</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">execute_wrapper</span><span class=\"p\">(</span><span class=\"n\">blocker</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">template_name</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>The parameters sent to the wrappers are:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">execute</span></code> – a callable, which should be invoked with the rest of the\nparameters in order to execute the query.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">sql</span></code> – a <code class=\"docutils literal notranslate\"><span class=\"pre\">str</span></code>, the SQL query to be sent to the database.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> – a list/tuple of parameter values for the SQL command, or a\nlist/tuple of lists/tuples if the wrapped call is <code class=\"docutils literal notranslate\"><span class=\"pre\">executemany()</span></code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">many</span></code> – a <code class=\"docutils literal notranslate\"><span class=\"pre\">bool</span></code> indicating whether the ultimately invoked call is\n<code class=\"docutils literal notranslate\"><span class=\"pre\">execute()</span></code> or <code class=\"docutils literal notranslate\"><span class=\"pre\">executemany()</span></code> (and whether <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> is expected to be\na sequence of values, or a sequence of sequences of values).</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code> – a dictionary with further data about the context of\ninvocation. This includes the connection and cursor.</p></li>\n</ul>\n<p>Using the parameters, a slightly more complex version of the blocker could\ninclude the connection name in the error message:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">blocker</span><span class=\"p\">(</span><span class=\"n\">execute</span><span class=\"p\">,</span> <span class=\"n\">sql</span><span class=\"p\">,</span> <span class=\"n\">params</span><span class=\"p\">,</span> <span class=\"n\">many</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">):</span>\n    <span class=\"n\">alias</span> <span class=\"o\">=</span> <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;connection&#39;</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">alias</span>\n    <span class=\"k\">raise</span> <span class=\"ne\">Exception</span><span class=\"p\">(</span><span class=\"s2\">&quot;Access to database &#39;</span><span class=\"si\">{}</span><span class=\"s2\">&#39; blocked here&quot;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span><span class=\"n\">alias</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>For a more complete example, a query logger could look like this:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">time</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">QueryLogger</span><span class=\"p\">:</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">queries</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__call__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">execute</span><span class=\"p\">,</span> <span class=\"n\">sql</span><span class=\"p\">,</span> <span class=\"n\">params</span><span class=\"p\">,</span> <span class=\"n\">many</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">):</span>\n        <span class=\"n\">current_query</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">&#39;sql&#39;</span><span class=\"p\">:</span> <span class=\"n\">sql</span><span class=\"p\">,</span> <span class=\"s1\">&#39;params&#39;</span><span class=\"p\">:</span> <span class=\"n\">params</span><span class=\"p\">,</span> <span class=\"s1\">&#39;many&#39;</span><span class=\"p\">:</span> <span class=\"n\">many</span><span class=\"p\">}</span>\n        <span class=\"n\">start</span> <span class=\"o\">=</span> <span class=\"n\">time</span><span class=\"o\">.</span><span class=\"n\">monotonic</span><span class=\"p\">()</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"n\">execute</span><span class=\"p\">(</span><span class=\"n\">sql</span><span class=\"p\">,</span> <span class=\"n\">params</span><span class=\"p\">,</span> <span class=\"n\">many</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">)</span>\n        <span class=\"k\">except</span> <span class=\"ne\">Exception</span> <span class=\"k\">as</span> <span class=\"n\">e</span><span class=\"p\">:</span>\n            <span class=\"n\">current_query</span><span class=\"p\">[</span><span class=\"s1\">&#39;status&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;error&#39;</span>\n            <span class=\"n\">current_query</span><span class=\"p\">[</span><span class=\"s1\">&#39;exception&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">e</span>\n            <span class=\"k\">raise</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"n\">current_query</span><span class=\"p\">[</span><span class=\"s1\">&#39;status&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;ok&#39;</span>\n            <span class=\"k\">return</span> <span class=\"n\">result</span>\n        <span class=\"k\">finally</span><span class=\"p\">:</span>\n            <span class=\"n\">duration</span> <span class=\"o\">=</span> <span class=\"n\">time</span><span class=\"o\">.</span><span class=\"n\">monotonic</span><span class=\"p\">()</span> <span class=\"o\">-</span> <span class=\"n\">start</span>\n            <span class=\"n\">current_query</span><span class=\"p\">[</span><span class=\"s1\">&#39;duration&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">duration</span>\n            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">queries</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">current_query</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>To use this, you would create a logger object and install it as a wrapper:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">connection</span>\n\n<span class=\"n\">ql</span> <span class=\"o\">=</span> <span class=\"n\">QueryLogger</span><span class=\"p\">()</span>\n<span class=\"k\">with</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">execute_wrapper</span><span class=\"p\">(</span><span class=\"n\">ql</span><span class=\"p\">):</span>\n    <span class=\"n\">do_queries</span><span class=\"p\">()</span>\n<span class=\"c1\"># Now we can print the log.</span>\n<span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">ql</span><span class=\"o\">.</span><span class=\"n\">queries</span><span class=\"p\">)</span>\n</code></pre></div>\n<section id=\"connection-execute-wrapper\">\n<h2><code class=\"docutils literal notranslate\"><span class=\"pre\">connection.execute_wrapper()</span></code><a class=\"heading-anchor\" href=\"#connection-execute-wrapper\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.backends.base.DatabaseWrapper.execute_wrapper\">\n<span class=\"sig-name descname\"><span class=\"pre\">execute_wrapper</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">wrapper</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.backends.base.DatabaseWrapper.execute_wrapper\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Returns a context manager which, when entered, installs a wrapper around\ndatabase query executions, and when exited, removes the wrapper. The wrapper is\ninstalled on the thread-local connection object.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">wrapper</span></code> is a callable taking five arguments.  It is called for every query\nexecution in the scope of the context manager, with arguments <code class=\"docutils literal notranslate\"><span class=\"pre\">execute</span></code>,\n<code class=\"docutils literal notranslate\"><span class=\"pre\">sql</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">many</span></code>, and <code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code> as described above. It’s\nexpected to call <code class=\"docutils literal notranslate\"><span class=\"pre\">execute(sql,</span> <span class=\"pre\">params,</span> <span class=\"pre\">many,</span> <span class=\"pre\">context)</span></code> and return the return\nvalue of that call.</p>\n</section>","rootId":"database-instrumentation","toc":[{"title":"connection.execute_wrapper()","anchor":"connection-execute-wrapper","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Using Django","url":"/el/4.1/topics/"},{"docname":"topics/db/index","title":"Models and databases","url":"/el/4.1/topics/db/"}],"prev":{"docname":"topics/db/optimization","title":"Database access optimization","url":"/el/4.1/topics/db/optimization/"},"next":{"docname":"topics/db/examples/index","title":"Examples of model relationship API usage","url":"/el/4.1/topics/db/examples/"},"formats":{"html":"/el/4.1/topics/db/instrumentation/","markdown":"/el/4.1/topics/db/instrumentation.md","json":"/el/4.1/topics/db/instrumentation.json"},"source":"https://github.com/django/django/blob/stable/4.1.x/docs/topics/db/instrumentation.txt","official":"https://docs.djangoproject.com/el/4.1/topics/db/instrumentation/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}