{"title":"Instrumentation de base de données","version":"2.1","locale":"fr","docname":"topics/db/instrumentation","url":"/fr/2.1/topics/db/instrumentation/","canonical":"https://djangodocs.dev/fr/2.1/topics/db/instrumentation/","summary":"New in Django 2.0 Pour vous aider à comprendre et à contrôler les requêtes produites par votre code, Django fournit un point d’accès pour installer des fonctions…","html":"<h1>Instrumentation de base de données<a class=\"heading-anchor\" href=\"#database-instrumentation\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<aside class=\"version-note version-added\" data-version=\"2.0\">\n<p class=\"version-note-title\">New in Django 2.0</p></aside>\n<p>Pour vous aider à comprendre et à contrôler les requêtes produites par votre code, Django fournit un point d’accès pour installer des fonctions enveloppantes autour de l’exécution des requêtes de base de données. Par exemple, ces fonctions peuvent compter les requêtes, mesurer leur durée, les journaliser ou même empêcher leur exécution (par ex. pour s’assurer qu’aucune requête ne soit exécutée lors du rendu d’un gabarit avec des données préchargées.</p>\n<p>Les fonctions enveloppantes sont structurées comme pour les <a class=\"reference internal\" href=\"/fr/2.1/topics/http/middleware/\"><span class=\"doc\">intergiciels</span></a> – il s’agit d’objets exécutables qui acceptent un autre exécutable dans l’un de leurs paramètres. Elles appellent ce dernier pour invoquer la requête de base de données (potentiellement enveloppée), et elles peuvent faire ce qu’elles veulent autour de cet appel. Elles sont cependant créées et installées par le code utilisateur, ce qui fait qu’elles n’ont pas besoin d’une fabrique distincte comme pour les intergiciels.</p>\n<p>L’installation d’une fonction enveloppante se fait dans un gestionnaire de contexte, ce qui rend ces fonctions temporaires et spécifiques à un certain flux de votre code.</p>\n<p>Comme mentionné ci-dessus, un exemple de fonction enveloppante est un bloqueur d’exécution de requête. Voici à quoi cela pourrait ressembler</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>Et cela serait utilisé dans une vue pour bloquer les requêtes provenant d’un gabarit, comme ceci</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>Les paramètres envoyés à la fonction enveloppante sont :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">execute</span></code> – un objet exécutable, qui devrait être appelé avec le reste des paramètres afin d’exécuter la requête.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">sql</span></code> – une chaîne <code class=\"docutils literal notranslate\"><span class=\"pre\">str</span></code>, la requête SQL qui sera envoyée à la base de données.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> – une liste (ou tuple) de paramètres à destination de la commande SQL, ou une liste de listes si l’appel enveloppé est <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> – une valeur booléenne indiquant si l’appel invoqué en définitive sera <code class=\"docutils literal notranslate\"><span class=\"pre\">execute()</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">executemany()</span></code> (et si <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> doit être une liste de valeurs ou une liste de listes de valeurs).</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code> – un dictionnaire avec des données supplémentaires sur le contexte de l’invocation. Cela inclut les éléments <code class=\"docutils literal notranslate\"><span class=\"pre\">connection</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">cursor</span></code>.</p></li>\n</ul>\n<p>En utilisant les paramètres, une version à peine plus complexe du bloqueur pourrait inclure le nom de la connexion dans le message d’erreur</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>Pour un exemple plus complet, un journaliseur de requête pourrait ressembler à ceci</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\">time</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\">time</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>Pour utiliser cela, il faut créer un objet de journalisation et l’installer comme enveloppeur</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\">Lien vers cette rubrique</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\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Renvoie un gestionnaire de contexte qui, en entrée, installe la fonction d’enveloppement autour des exécutions de requêtes de base de données, et en sortie enlève cette fonction. La fonction d’enveloppement est installée sur l’objet connexion du fil d’exécution local.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">wrapper</span></code> est un objet exécutable acceptant cinq paramètres. Il est appelé lors de chaque exécution de requête dans la portée du gestionnaire de contexte, avec les arguments <code class=\"docutils literal notranslate\"><span class=\"pre\">execute</span></code>, <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> et <code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code>, tels que décrits ci-dessus. Cet exécutable est censé appeler <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> et renvoyer la valeur de renvoi de cet appel.</p>\n</section>","rootId":"database-instrumentation","toc":[{"title":"connection.execute_wrapper()","anchor":"connection-execute-wrapper","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/2.1/topics/"},{"docname":"topics/db/index","title":"Modèles et bases de données","url":"/fr/2.1/topics/db/"}],"prev":{"docname":"topics/db/optimization","title":"Optimisation de l’accès à la base de données","url":"/fr/2.1/topics/db/optimization/"},"next":{"docname":"topics/db/examples/index","title":"Exemples d’utilisation de l’API de relations entre modèles","url":"/fr/2.1/topics/db/examples/"},"formats":{"html":"/fr/2.1/topics/db/instrumentation/","markdown":"/fr/2.1/topics/db/instrumentation.md","json":"/fr/2.1/topics/db/instrumentation.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/topics/db/instrumentation.txt","official":"https://docs.djangoproject.com/fr/2.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","pt-br","ko","es","el","pl"]}