{"title":"Transactions de base de données","version":"1.11","locale":"fr","docname":"topics/db/transactions","url":"/fr/1.11/topics/db/transactions/","canonical":"https://djangodocs.dev/fr/1.11/topics/db/transactions/","summary":"Django donne quelques moyens de contrôler la gestion des transactions de base de données. Gestion des transactions de base de données Lien vers cette rubrique #…","html":"<span id=\"database-transactions\"></span><h1>Transactions de base de données<a class=\"heading-anchor\" href=\"#module-django.db.transaction\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django donne quelques moyens de contrôler la gestion des transactions de base de données.</p>\n<section id=\"managing-database-transactions\">\n<h2>Gestion des transactions de base de données<a class=\"heading-anchor\" href=\"#managing-database-transactions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"django-s-default-transaction-behavior\">\n<h3>Comportement de transaction par défaut de Django<a class=\"heading-anchor\" href=\"#django-s-default-transaction-behavior\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le comportement par défaut de Django est de fonctionner en mode de validation automatique (« autocommit »). Chaque requête est immédiatement validée dans la base de données, sauf si une transaction est en cours. <a class=\"reference internal\" href=\"#autocommit-details\"><span class=\"std std-ref\">Voir ci-dessous pour plus de détails</span></a>.</p>\n<p>Django utilise automatiquement des transactions ou des points de sauvegarde pour garantir l’intégrité des opérations de l’ORM qui nécessitent plusieurs requêtes, particulièrement les requêtes <a class=\"reference internal\" href=\"/fr/1.11/topics/db/queries/#topics-db-queries-delete\"><span class=\"std std-ref\">delete()</span></a> et <a class=\"reference internal\" href=\"/fr/1.11/topics/db/queries/#topics-db-queries-update\"><span class=\"std std-ref\">update()</span></a>.</p>\n<p>La classe <a class=\"reference internal\" href=\"/fr/1.11/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a> de Django englobe aussi chaque test dans une transaction pour des raisons de performance.</p>\n</section>\n<section id=\"tying-transactions-to-http-requests\">\n<span id=\"id1\"></span><h3>Couplage des transactions aux requêtes HTTP<a class=\"heading-anchor\" href=\"#tying-transactions-to-http-requests\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Une façon fréquente de gérer les transactions sur le Web est d’envelopper chaque requête dans une transaction. Définissez <a class=\"reference internal\" href=\"/fr/1.11/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a> à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> dans la configuration de chaque base de données pour laquelle vous souhaitez activer ce comportement.</p>\n<p>Voici comment cela fonctionne. Avant d’appeler une fonction de vue, Django démarre une transaction. Si la réponse est renvoyée sans problème particulier, Django valide la transaction. Si la vue génère une exception, Django annule la transaction.</p>\n<p>Il est possible d’effectuer des sous-transactions à l’aide de points de sauvegarde dans le code de la vue, typiquement avec le gestionnaire de contexte <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>. Cependant, quand la vue se termine, soit tous les changements sont validés, soit tous sont annulés.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Bien que la simplicité de ce modèle de transaction est attrayant, il devient inefficace lorsque le trafic augmente. L’ouverture d’une transaction pour chaque vue présente un certain coût. L’impact sur la performance dépend de la manière dont vos applications font usage des requêtes et de la manière dont la base de données gère les verrous.</p>\n</aside>\n<aside class=\"admonition-per-request-transactions-and-streaming-responses admonition\">\n<p class=\"admonition-title\">Transactions par requête et réponses en flux</p>\n<p>Lorsqu’une vue renvoie une réponse en flux (<a class=\"reference internal\" href=\"/fr/1.11/ref/request-response/#django.http.StreamingHttpResponse\" title=\"django.http.StreamingHttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">StreamingHttpResponse</span></code></a>), la lecture du contenu de la réponse exécute fréquemment du code pour générer le contenu. Comme la vue s’est déjà terminée, ce code s’exécute en dehors de la transaction.</p>\n<p>De manière générale, il n’est pas conseillé d’écrire dans la base de données durant la génération d’une réponse en flux, car il n’y a plus de méthode raisonnable pour gérer les erreurs après le début de l’envoi de la réponse.</p>\n</aside>\n<p>En pratique, cette fonctionnalité ne fait qu’envelopper chaque fonction de vue dans le décorateur <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> décrit ci-dessous.</p>\n<p>Notez que seule l’exécution de la vue est incluse dans la transaction. Les intergiciels s’exécutent en dehors de la transaction, de même que le rendu des réponses par gabarit.</p>\n<p>Lorsque <a class=\"reference internal\" href=\"/fr/1.11/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a> est actif, il est toujours possible d’empêcher les vues de s’exécuter dans une transaction.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.non_atomic_requests\">\n<span class=\"sig-name descname\"><span class=\"pre\">non_atomic_requests</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.non_atomic_requests\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Ce décorateur annule l’effet de <a class=\"reference internal\" href=\"/fr/1.11/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a> pour une vue donnée :</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\">transaction</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">non_atomic_requests</span>\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\">do_stuff</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">non_atomic_requests</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;other&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_other_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">do_stuff_on_the_other_database</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Cela ne fonctionne que lorsque le décorateur est appliqué à la vue elle-même.</p>\n</dd></dl>\n\n</section>\n<section id=\"controlling-transactions-explicitly\">\n<h3>Contrôle explicite des transactions<a class=\"heading-anchor\" href=\"#controlling-transactions-explicitly\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django fournit une API unifiée pour contrôler les transactions de base de données.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.atomic\">\n<span class=\"sig-name descname\"><span class=\"pre\">atomic</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">savepoint</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.atomic\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>L’atomicité est la propriété de base des transactions de base de données. <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> permet de créer un bloc de code à l’intérieur duquel l’atomicité est garantie au niveau de la base de données. Si le bloc de code se termine avec succès, les modifications sont validées dans la base de données. Si une exception apparaît, les modifications sont annulées en bloc.</p>\n<p>Les blocs <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> peuvent être imbriqués. Dans ce cas, lorsqu’un bloc intérieur se termine avec succès, ses effets peuvent encore être annulés si une exception est générée plus loin dans le bloc englobant.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> peut être utilisé comme <span class=\"xref std std-term\">décorateur</span>:</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\">transaction</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"c1\"># This code executes inside a transaction.</span>\n    <span class=\"n\">do_stuff</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>et comme <span class=\"xref std std-term\">gestionnaire de contexte</span>:</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\">transaction</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"c1\"># This code executes in autocommit mode (Django&#39;s default).</span>\n    <span class=\"n\">do_stuff</span><span class=\"p\">()</span>\n\n    <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n        <span class=\"c1\"># This code executes inside a transaction.</span>\n        <span class=\"n\">do_more_stuff</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>L’insertion d”<code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> dans un bloc try/except est une manière naturelle de gérer les erreurs d’intégrité :</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\">IntegrityError</span><span class=\"p\">,</span> <span class=\"n\">transaction</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">create_parent</span><span class=\"p\">()</span>\n\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n            <span class=\"n\">generate_relationships</span><span class=\"p\">()</span>\n    <span class=\"k\">except</span> <span class=\"n\">IntegrityError</span><span class=\"p\">:</span>\n        <span class=\"n\">handle_exception</span><span class=\"p\">()</span>\n\n    <span class=\"n\">add_children</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Dans cet exemple, même si <code class=\"docutils literal notranslate\"><span class=\"pre\">generate_relationships()</span></code> provoque une erreur de base de données en cassant une contrainte d’intégrité, vous pouvez exécuter des requêtes dans <code class=\"docutils literal notranslate\"><span class=\"pre\">add_children()</span></code> et les modifications de <code class=\"docutils literal notranslate\"><span class=\"pre\">create_parent()</span></code> sont toujours présentes. Notez que toute opération exécutée dans <code class=\"docutils literal notranslate\"><span class=\"pre\">generate_relationships()</span></code> aura déjà été annulée proprement lorsque <code class=\"docutils literal notranslate\"><span class=\"pre\">handle_exception()</span></code> est appelée, ce qui fait que le gestionnaire d’exception peut très bien agir au niveau de la base de données si nécessaire.</p>\n<aside class=\"admonition-avoid-catching-exceptions-inside-atomic admonition\">\n<p class=\"admonition-title\">Évitez d’intercepter des exceptions à l’intérieur d”<code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>!</p>\n<p>À la sortie d’un bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>, Django examine si la sortie se fait normalement ou par une exception afin de déterminer s’il doit valider ou annuler la transaction. Si vous interceptez et gérez des exceptions à l’intérieur du bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>, vous cachez à Django le fait qu’un problème est survenu. Cela peut aboutir à des comportements inattendus.</p>\n<p>Ce problème concerne plus spécifiquement les exceptions <a class=\"reference internal\" href=\"/fr/1.11/ref/exceptions/#django.db.DatabaseError\" title=\"django.db.DatabaseError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">DatabaseError</span></code></a> et ses sous-classes telles que  <a class=\"reference internal\" href=\"/fr/1.11/ref/exceptions/#django.db.IntegrityError\" title=\"django.db.IntegrityError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">IntegrityError</span></code></a>. Après une telle erreur, la transaction est cassée et Django procédera à son annulation dès la sortie du bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>. Si vous essayez d’exécuter des requêtes en base de données avant que l’annulation intervienne, Django générera une exception <a class=\"reference internal\" href=\"/fr/1.11/ref/exceptions/#django.db.transaction.TransactionManagementError\" title=\"django.db.transaction.TransactionManagementError\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionManagementError</span></code></a>. Vous pouvez également rencontrer ce comportement lorsqu’un gestionnaire de signal lié à l’ORM génère une exception.</p>\n<p>La manière correcte d’intercepter les erreurs de base de données est de le faire autour du bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> comme dans l’exemple ci-dessus. Si nécessaire, ajoutez un bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> supplémentaire à cet effet. Cette stratégie présente un autre avantage : elle délimite explicitement les opérations qui seront annulées si une exception se produit.</p>\n<p>Si vous interceptez les exceptions générées par des requêtes SQL brutes, le comportement de Django n’est pas défini et dépend de la base de données.</p>\n</aside>\n<aside class=\"admonition-you-may-need-to-manually-revert-model-state-when-rolling-back-a-transaction admonition\">\n<p class=\"admonition-title\">Vous devrez peut-être réinitialiser manuellement l’état du modèle lors du renversement d’une transaction.</p>\n<p>Les valeurs des champs d’un modèle ne seront pas réinitialisées lorsqu’une rétrogradation des transactions se produit. Cela pourrait conduire à un état de modèle incompatible à moins que vous ne restauriez manuellement les valeurs de champ d’origine.</p>\n<p>Par exemple, considérons <code class=\"docutils literal notranslate\"><span class=\"pre\">MyModel</span></code> avec un champ <code class=\"docutils literal notranslate\"><span class=\"pre\">active</span></code>, cet extrait garantit que la vérification à la fin <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span> <span class=\"pre\">obj.active</span></code> utilise la valeur correcte si la mise à jour de <code class=\"docutils literal notranslate\"><span class=\"pre\">active</span></code> vers <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> échoue dans la transaction</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\">DatabaseError</span><span class=\"p\">,</span> <span class=\"n\">transaction</span>\n\n<span class=\"n\">obj</span> <span class=\"o\">=</span> <span class=\"n\">MyModel</span><span class=\"p\">(</span><span class=\"n\">active</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n<span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">active</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n        <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n<span class=\"k\">except</span> <span class=\"n\">DatabaseError</span><span class=\"p\">:</span>\n    <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">active</span> <span class=\"o\">=</span> <span class=\"kc\">False</span>\n\n<span class=\"k\">if</span> <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">active</span><span class=\"p\">:</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</aside>\n<p>Afin de garantir l’atomicité, <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> désactive certaines API. Si vous tentez de valider une transaction, de l’annuler ou de modifier l’état de validation automatique de la connexion de base de données à l’intérieur d’un bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>, vous obtiendrez une exception.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> accepte un paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> devant correspondre au nom d’une base de données. Si ce paramètre n’est pas présent, Django utilise la base de données <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code>.</p>\n<p>En arrière-plan, le code de gestion des transactions de Django :</p>\n<ul class=\"simple\">\n<li><p>ouvre une transaction lorsqu’il entre dans le premier bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>;</p></li>\n<li><p>crée un point de sauvegarde lorsqu’il entre dans un bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> imbriqué ;</p></li>\n<li><p>libère le point de sauvegarde ou annule la transaction jusqu’au point de sauvegarde en quittant le bloc imbriqué ;</p></li>\n<li><p>valide ou annule la transaction en quittant le bloc de départ.</p></li>\n</ul>\n<p>Vous pouvez désactiver la création de points de sauvegarde pour les blocs imbriqués en définissant le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">savepoint</span></code> à <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>. Si une exception survient, Django procède à l’annulation de la transaction au moment de quitter le premier bloc ayant un point de sauvegarde, le cas échéant, ou le bloc initial sinon. L’atomicité est toujours garantie par la transaction du bloc initial. Cette option ne devrait être utilisée que si la création des points de sauvegarde affecte les performances de manière évidente. Le désavantage est que cela casse la gestion d’erreurs telle que décrite précédemment.</p>\n<p>Il est possible d’utiliser <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> lorsque la validation automatique est désactivée. Seuls des points de sauvegarde seront utilisés, même pour le bloc initial.</p>\n</dd></dl>\n\n<aside class=\"admonition-performance-considerations admonition\">\n<p class=\"admonition-title\">Considérations sur la performance</p>\n<p>Les transactions ouvertes constituent une pénalité de performance pour votre serveur de base de données. Pour minimiser cet impact, gardez vos transactions aussi brèves que possible. C’est particulièrement important si vous utilisez <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> dans des processus de longue durée, en dehors du cycle requête/réponse de Django.</p>\n</aside>\n</section>\n</section>\n<section id=\"autocommit\">\n<h2>Autocommit<a class=\"heading-anchor\" href=\"#autocommit\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"why-django-uses-autocommit\">\n<span id=\"autocommit-details\"></span><h3>Pourquoi Django utilise-t-il l’autocommit<a class=\"heading-anchor\" href=\"#why-django-uses-autocommit\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Dans le standard SQL, chaque requête SQL démarre une transaction, sauf s’il y en a déjà une en cours. De telles transactions doivent ensuite être explicitement soit validées (commit), soit annulées (rollback).</p>\n<p>Ce n’est pas toujours très pratique pour les développeurs d’applications. Pour contourner ce problème, la plupart des bases de données mettent à disposition un mode « autocommit ». Lorsque ce mode est actif et qu’il n’y a pas de transaction ouverte, chaque requête SQL est englobée dans sa propre transaction. En d’autres termes, chacune de ces requêtes non seulement démarre une transaction, mais cette transaction est aussi automatiquement validée ou annulée en fonction du résultat de la requête.</p>\n<p><span class=\"target\" id=\"index-4\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a>, la spécification d’API de base de données Python v2.0, exige que le mode autocommit soit initialement désactivé. Django surcharge ce comportement par défaut et active le mode autocommit.</p>\n<p>Pour empêcher cela, vous pouvez <a class=\"reference internal\" href=\"#deactivate-transaction-management\"><span class=\"std std-ref\">désactiver la gestion des transactions</span></a>, mais ce n’est pas recommandé.</p>\n</section>\n<section id=\"deactivating-transaction-management\">\n<span id=\"deactivate-transaction-management\"></span><h3>Désactivation de la gestion des transaction<a class=\"heading-anchor\" href=\"#deactivating-transaction-management\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Vous pouvez désactiver totalement la gestion des transactions de Django pour une base de données précise en définissant <a class=\"reference internal\" href=\"/fr/1.11/ref/settings/#std-setting-DATABASE-AUTOCOMMIT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTOCOMMIT</span></code></a> à <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> dans sa configuration. Si vous faites cela, Django n’activera pas le mode autocommit et n’effectue aucune opération de commit. Vous obtenez alors le comportement habituel de la bibliothèque de base de données sous-jacente.</p>\n<p>Cela demande que vous effectuiez un commit explicite de chaque transaction, même de celles initiées par Django ou par des bibliothèques tierces. Ainsi, cela convient mieux à des situations où vous souhaitez mettre en place votre propre intergiciel de gestion des transactions ou que vous faites des choses plutôt étranges.</p>\n</section>\n</section>\n<section id=\"performing-actions-after-commit\">\n<h2>Lancement d’actions après le commit<a class=\"heading-anchor\" href=\"#performing-actions-after-commit\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Il peut arriver que vous ayez besoin d’effectuer une action liée à la transaction de base de données en cours, mais seulement si la transaction se termine par un commit réussi. On peut citer comme exemple une tâche <a class=\"reference external\" href=\"http://www.celeryproject.org/\">Celery</a>, une notification par courriel ou une invalidation de cache.</p>\n<p>Django fournit la fonction <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> pour inscrire des fonctions de rappel qui seront exécutées après le commit réussi de la transaction :</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.on_commit\">\n<span class=\"sig-name descname\"><span class=\"pre\">on_commit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">func</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.on_commit\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Passez une fonction (qui n’accepte pas de paramètre) à <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a>:</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\">transaction</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_something</span><span class=\"p\">():</span>\n    <span class=\"k\">pass</span>  <span class=\"c1\"># send a mail, invalidate a cache, fire off a Celery task, etc.</span>\n\n<span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">do_something</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Il est aussi possible d’envelopper la fonction dans une lambda :</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=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"k\">lambda</span><span class=\"p\">:</span> <span class=\"n\">some_celery_task</span><span class=\"o\">.</span><span class=\"n\">delay</span><span class=\"p\">(</span><span class=\"s1\">&#39;arg1&#39;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>La fonction transmise sera appelée immédiatement après une écriture potentielle de base de données pour laquelle <code class=\"docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code> a été appelée et se terminant par un commit réussi.</p>\n<p>Si vous appelez <code class=\"docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code> alors qu’aucune transaction n’est en cours, la fonction transmise est immédiatement exécutée.</p>\n<p>Si cette écriture de base de données potentielle se trouve annulée (rollback), typiquement lorsqu’une exception non traitée est générée dans le bloc <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>, la fonction est ignorée et ne sera jamais appelée.</p>\n<section id=\"savepoints\">\n<h3>Points de sauvegarde (« savepoints »)<a class=\"heading-anchor\" href=\"#savepoints\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les points de sauvegarde (blocs <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> imbriqués) sont gérés correctement. C’est-à-dire qu’une fonction inscrite par <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> après un point de sauvegarde (dans un bloc <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> imbriqué) sera appelée après le commit de la transaction la plus externe, mais pas dans le cas où une annulation (rollback) de ce point de sauvegarde ou de tout autre point de sauvegarde précédent se produit pendant la transaction :</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\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Outer atomic, start a new transaction</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">foo</span><span class=\"p\">)</span>\n\n    <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Inner atomic block, create a savepoint</span>\n        <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">bar</span><span class=\"p\">)</span>\n\n<span class=\"c1\"># foo() and then bar() will be called when leaving the outermost block</span>\n</code></pre></div>\n<p>D’un autre côté, lorsqu’un point de sauvegarde est annulé (en raison de l’apparition d’une exception), la fonction définie à l’intérieur de point de sauvegarde ne sera pas appelée :</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\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Outer atomic, start a new transaction</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">foo</span><span class=\"p\">)</span>\n\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Inner atomic block, create a savepoint</span>\n            <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">bar</span><span class=\"p\">)</span>\n            <span class=\"k\">raise</span> <span class=\"n\">SomeError</span><span class=\"p\">()</span>  <span class=\"c1\"># Raising an exception - abort the savepoint</span>\n    <span class=\"k\">except</span> <span class=\"n\">SomeError</span><span class=\"p\">:</span>\n        <span class=\"k\">pass</span>\n\n<span class=\"c1\"># foo() will be called, but not bar()</span>\n</code></pre></div>\n</section>\n<section id=\"order-of-execution\">\n<h3>Ordre d’exécution<a class=\"heading-anchor\" href=\"#order-of-execution\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les fonctions <code class=\"docutils literal notranslate\"><span class=\"pre\">on_commit</span></code> d’une transaction donnée sont exécutées dans l’ordre de leur inscription.</p>\n</section>\n<section id=\"exception-handling\">\n<h3>Gestion des exceptions<a class=\"heading-anchor\" href=\"#exception-handling\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si l’une des fonctions <code class=\"docutils literal notranslate\"><span class=\"pre\">on_commit</span></code> dans une transaction donnée génère une exception non traitée, aucune fonction inscrite à la suite dans cette même transaction ne sera exécutée. Ceci correspond évidemment au même comportement qui se serait produit si vous aviez exécuté ces fonctions séquentiellement vous-même sans <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a>.</p>\n</section>\n<section id=\"timing-of-execution\">\n<h3>Ordre d’exécution<a class=\"heading-anchor\" href=\"#timing-of-execution\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les fonctions de rappel sont exécutées <em>après</em> un commit réussi, ce qui fait qu’une exception dans une fonction de rappel ne provoquera pas d’annulation de transaction. Elles ne sont exécutées qu’en cas de succès de la transaction, mais <em>sans</em> faire partie de la transaction. Pour les cas d’utilisation visés (notifications par courriel, tâches Celery, etc.) cela devrait convenir. Dans le cas contraire (par exemple si l’action à effectuer est si critique que son échec devrait aussi faire échouer la transaction principale), il ne faut alors pas exploiter le point d’entrée <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a>. Une alternative possible est un <a class=\"reference external\" href=\"http://initd.org/psycopg/docs/usage.html#tpc\">commit en deux phases</a> tel que la <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Two-phase_commit_protocol\">prise en charge du protocole de commit en deux phases de psycopg</a> ou les <a class=\"reference external\" href=\"https://www.python.org/dev/peps/pep-0249/#optional-two-phase-commit-extensions\">extensions facultatives de commit en deux phases dans la spécification DB-API de Python</a>.</p>\n<p>Les fonctions de rappel ne sont pas appelées avant que la connexion ne repasse en mode autocommit après le commit (sinon toute requête dans une fonction de rappel ouvrirait une transaction implicite empêchant la connexion de repasser en mode de commit automatique).</p>\n<p>Si l’on se trouve déjà en mode autocommit et en-dehors d’un bloc <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>, la fonction est immédiatement exécutée sans attendre de commit.</p>\n<p>Les fonctions <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>on_commit``ne fonctionnent qu’en <a class=\"reference internal\" href=\"#managing-autocommit\"><span class=\"std std-ref\">mode autocommit</span></a> et avec l’API de transaction <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> (ou <a class=\"reference internal\" href=\"/fr/1.11/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a>). L’appel à <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> lorsque le mode autocommit est désactivé et en-dehors d’un bloc atomique produit une erreur.</p>\n</section>\n<section id=\"use-in-tests\">\n<h3>Utilisation dans les tests<a class=\"heading-anchor\" href=\"#use-in-tests\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>La classe <a class=\"reference internal\" href=\"/fr/1.11/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a> de Django enveloppe chaque test dans une transaction et annule cette transaction après chaque test, afin de garantir l’isolation des tests. Cela signifie qu’aucune transaction n’est réellement suivie d’un commit et donc qu’aucune des fonctions de rappel <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> ne sera jamais exécutée. Si vous avez besoin de tester les résultats d’une fonction de rappel <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a>, utilisez plutôt une classe <a class=\"reference internal\" href=\"/fr/1.11/topics/testing/tools/#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a>.</p>\n</section>\n<section id=\"why-no-rollback-hook\">\n<h3>Pourquoi pas de point d’entrée pour les transactions annulées ?<a class=\"heading-anchor\" href=\"#why-no-rollback-hook\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Un point d’entrée pour les transactions annulées (rollback) est plus difficile à implémenter de manière solide qu’un point d’entrée de commit, car plusieurs choses peuvent provoquer une annulation implicite.</p>\n<p>Par exemple, si la connexion à la base de données s’interrompt en raison d’un processus tué sans aucune chance de terminaison propre, le point d’entrée d’annulation ne sera jamais exécuté.</p>\n<p>La solution est simple : au lieu de faire quelque chose à l’intérieur du bloc atomique (transaction) puis de le défaire en cas d’échec de transaction, utilisez <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> pour déporter la tâche au moment où la transaction a réussi. C’est beaucoup plus facile de défaire quelque chose que l’on n’a jamais fait !</p>\n</section>\n</section>\n<section id=\"low-level-apis\">\n<h2>API de bas niveau<a class=\"heading-anchor\" href=\"#low-level-apis\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Si possible, préférez toujours <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>. Il prend en compte les particularités de chaque base de données et évite les opérations non valides.</p>\n<p>L’API de bas niveau n’est utile que si vous implémentez votre propre gestion des transactions.</p>\n</aside>\n<section id=\"managing-autocommit\">\n<span id=\"id2\"></span><h3>Autocommit<a class=\"heading-anchor\" href=\"#managing-autocommit\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django fournit une API basique dans le module <a class=\"reference internal\" href=\"#module-django.db.transaction\" title=\"django.db.transaction\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.db.transaction</span></code></a> pour gérer l’état de validation automatique de chaque connexion de base de données.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.get_autocommit\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_autocommit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.get_autocommit\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.set_autocommit\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_autocommit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">autocommit</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.set_autocommit\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Ces fonctions acceptent un paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> qui doit correspondre au nom d’une base de données. Si ce paramètre n’est pas présent, Django utilise la base de données <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code>.</p>\n<p>La validation automatique (« autocommit ») est initialement activée. Si vous la désactivez, il est de votre responsabilité de la restaurer ensuite.</p>\n<p>Dès que vous désactivez la validation automatique, vous obtenez le comportement par défaut de votre adaptateur de base de données et Django ne vous aide plus. Même si ce comportement fait l’objet de la <span class=\"target\" id=\"index-5\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a>, les implémentations des adaptateurs ne sont pas toujours cohérentes entre elles. Parcourez attentivement la documentation de l’adaptateur que vous utilisez.</p>\n<p>Vous devez vous assurer qu’aucune transaction n’est pendante, généralement en appelant <a class=\"reference internal\" href=\"#django.db.transaction.commit\" title=\"django.db.transaction.commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">commit()</span></code></a> ou <a class=\"reference internal\" href=\"#django.db.transaction.rollback\" title=\"django.db.transaction.rollback\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">rollback()</span></code></a> avant de réactiver la validation automatique.</p>\n<p>Django refuse de désactiver la validation automatique lorsqu’un bloc <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> est actif, car l’atomicité ne serait alors plus respectée.</p>\n</section>\n<section id=\"transactions\">\n<h3>Transactions<a class=\"heading-anchor\" href=\"#transactions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Une transaction est un ensemble atomique de requêtes de base de données. Même si votre programme se plante, la base de données garantit que soit tous les changements seront appliqués, soit aucun.</p>\n<p>Django n’offre pas d’API pour démarrer une transaction. La manière attendue de démarrer une transaction est de désactiver la validation automatique avec <a class=\"reference internal\" href=\"#django.db.transaction.set_autocommit\" title=\"django.db.transaction.set_autocommit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">set_autocommit()</span></code></a>.</p>\n<p>Une fois dans la transaction, vous pouvez choisir d’appliquer les modifications effectuées jusqu’à ce point avec <a class=\"reference internal\" href=\"#django.db.transaction.commit\" title=\"django.db.transaction.commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">commit()</span></code></a>, ou de toutes les annuler avec <a class=\"reference internal\" href=\"#django.db.transaction.rollback\" title=\"django.db.transaction.rollback\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">rollback()</span></code></a>. Ces fonctions sont définies dans <a class=\"reference internal\" href=\"#module-django.db.transaction\" title=\"django.db.transaction\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.db.transaction</span></code></a>.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.commit\">\n<span class=\"sig-name descname\"><span class=\"pre\">commit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.commit\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.rollback\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Ces fonctions acceptent un paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> qui doit correspondre au nom d’une base de données. Si ce paramètre n’est pas présent, Django utilise la base de données <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code>.</p>\n<p>Django refuse de valider ou d’annuler une transaction lorsqu’un bloc <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> est actif, car l’atomicité ne serait alors plus respectée.</p>\n</section>\n<section id=\"topics-db-transactions-savepoints\">\n<span id=\"id3\"></span><h3>Points de sauvegarde (« savepoints »)<a class=\"heading-anchor\" href=\"#topics-db-transactions-savepoints\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Un point de sauvegarde est un marqueur dans une transaction qui vous permet d’annuler une transaction en partie, plutôt que dans sa totalité. Les points de sauvegarde sont disponibles pour les moteurs SQLite (≥ 3.6.8), PostgreSQL, Oracle et MySQL (avec le moteur de stockage InnoDB). D’autres moteurs fournissent les fonctions des points de sauvegarde, mais ces fonctions sont vides, elles ne font rien du tout.</p>\n<p>Les points de sauvegarde ne sont pas particulièrement utiles quand la validation automatique est active, ce qui est le comportement par défaut de Django. Cependant, dès que vous ouvrez une transaction avec <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>, vous accumulez une série d’opérations de base de données en attente de validation ou d’annulation. Lorsque vous annulez avec un « rollback », toute la transaction est annulée Les points de sauvegarde permettent d’annuler des opérations de manière plus sélective, plutôt que d’annuler en bloc comme le fait <code class=\"docutils literal notranslate\"><span class=\"pre\">transaction.rollback()</span></code>.</p>\n<p>Lorsque le décorateur <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> est imbriqué, il crée un point de sauvegarde pour permettre une validation ou une annulation partielle. Vous êtes fortement encouragé à utiliser <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> plutôt que les fonctions présentées ci-dessous, mais elles font tout de même partie de l’API publique, et il n’est pas prévu de les rendre obsolètes.</p>\n<p>Chacune de ces fonctions accepte un paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> devant correspondre au nom de la base de données pour laquelle le comportement s’applique. Si aucun paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> n’est transmis, c’est la base de données <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code> qui est utilisée.</p>\n<p>Les points de sauvegarde sont contrôlés par trois fonctions dans <a class=\"reference internal\" href=\"#module-django.db.transaction\" title=\"django.db.transaction\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.db.transaction</span></code></a>:</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.savepoint\">\n<span class=\"sig-name descname\"><span class=\"pre\">savepoint</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.savepoint\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Crée un nouveau point de sauvegarde. Un point est marqué dans la transaction, à un état qui est reconnu comme « bon ». Renvoie l’identifiant du point de sauvegarde (<code class=\"docutils literal notranslate\"><span class=\"pre\">sid</span></code>).</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.savepoint_commit\">\n<span class=\"sig-name descname\"><span class=\"pre\">savepoint_commit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sid</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.savepoint_commit\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Libère le point de sauvegarde <code class=\"docutils literal notranslate\"><span class=\"pre\">sid</span></code>. Les modifications effectuées depuis la création du point de sauvegarde sont intégrées dans la transaction.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.savepoint_rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">savepoint_rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sid</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.savepoint_rollback\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Annule la transaction en revenant au point de sauvegarde <code class=\"docutils literal notranslate\"><span class=\"pre\">sid</span></code>.</p>\n</dd></dl>\n\n<p>Ces fonctions ne font rien si les points de sauvegarde ne sont pas pris en charge ou si la base de données est en mode de validation automatique.</p>\n<p>Une fonction utilitaire est également disponible :</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.clean_savepoints\">\n<span class=\"sig-name descname\"><span class=\"pre\">clean_savepoints</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.clean_savepoints\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Réinitialise le compteur utilisé pour générer les identifiants uniques des points de sauvegarde.</p>\n</dd></dl>\n\n<p>L’exemple suivant illustre l’utilisation des points de sauvegarde :</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\">transaction</span>\n\n<span class=\"c1\"># open a transaction</span>\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n\n    <span class=\"n\">a</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n    <span class=\"c1\"># transaction now contains a.save()</span>\n\n    <span class=\"n\">sid</span> <span class=\"o\">=</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint</span><span class=\"p\">()</span>\n\n    <span class=\"n\">b</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n    <span class=\"c1\"># transaction now contains a.save() and b.save()</span>\n\n    <span class=\"k\">if</span> <span class=\"n\">want_to_keep_b</span><span class=\"p\">:</span>\n        <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_commit</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n        <span class=\"c1\"># open transaction still contains a.save() and b.save()</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_rollback</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n        <span class=\"c1\"># open transaction now contains only a.save()</span>\n</code></pre></div>\n<p>Les points de sauvegarde peuvent être utilisés pour se rétablir après une erreur de base de données en effectuant une annulation partielle des opérations. Si vous faites cela à l’intérieur d’un bloc <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>, tout le bloc sera quand même annulé, car Django ne sait pas que vous avez géré la situation à un plus bas niveau ! Pour empêcher cela, vous pouvez contrôler le comportement d’annulation avec les fonctions suivantes.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.get_rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.get_rollback\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.set_rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">rollback</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.set_rollback\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>En définissant le drapeau <code class=\"docutils literal notranslate\"><span class=\"pre\">rollback</span></code> à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>, vous forcez une annulation lorsque vous sortez du bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> le plus proche. Cela peut être utile pour provoquer une annulation sans générer d’exception.</p>\n<p>En le définissant à <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>, vous empêchez une telle annulation. Avant de faire cela, assurez-vous d’avoir bien annulé la transaction jusqu’à un point de sauvegarde en bon état à l’intérieur du bloc <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> actuel. Sinon, vous cassez l’atomicité et des corruptions de données peuvent apparaître.</p>\n</section>\n</section>\n<section id=\"database-specific-notes\">\n<h2>Notes spécifiques à certaines bases de données<a class=\"heading-anchor\" href=\"#database-specific-notes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"savepoints-in-sqlite\">\n<span id=\"id4\"></span><h3>Points de sauvegarde dans<a class=\"heading-anchor\" href=\"#savepoints-in-sqlite\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Même si les points de sauvegarde sont pris à charge à partir de SQLite ≥ 3.6.8, un défaut de conception dans le module <a class=\"reference external\" href=\"https://docs.python.org/3/library/sqlite3.html#module-sqlite3\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">sqlite3</span></code></a> les rend presque inutilisables.</p>\n<p>Lorsque la validation automatique est active, les points de sauvegarde n’ont pas de raison d’être. Dans le cas contraire, <a class=\"reference external\" href=\"https://docs.python.org/3/library/sqlite3.html#module-sqlite3\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">sqlite3</span></code></a> valide implicitement la transaction avant les instructions de points de sauvegarde (en fait, il valide avant toute instruction autre que <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">INSERT</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">UPDATE</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">DELETE</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">REPLACE</span></code>). Ce bogue a deux conséquences :</p>\n<ul class=\"simple\">\n<li><p>L’API de bas niveau des points de sauvegarde n’est utilisable qu’à l’intérieur d’une transaction, c’est-à-dire dans un bloc <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>.</p></li>\n<li><p>Il est impossible d’utiliser <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> lorsque la validation automatique est désactivée.</p></li>\n</ul>\n</section>\n<section id=\"transactions-in-mysql\">\n<h3>Transactions dans MySQL<a class=\"heading-anchor\" href=\"#transactions-in-mysql\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si vous utilisez MySQL, la prise en charge des transactions par vos tables varie ; tout dépend de la version de MySQL et des types de tables que vous utilisez (par « type de table », nous entendons quelque chose comme « InnoDB » ou « MyISAM »). Les particularités des transactions de MySQL vont au-delà du thème de cette documentation, mais le site de MySQL possède des <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/sql-syntax-transactions.html\">informations sur les transactions dans MySQL</a>.</p>\n<p>Si votre configuration MySQL ne gère <em>pas</em> les transactions, Django fonctionne toujours en mode de validation automatique : les instructions sont exécutées et validées dès qu’elles sont émises. Si votre configuration MySQL <em>gère</em> les transactions, Django traite les transactions comme expliqué dans ce document.</p>\n</section>\n<section id=\"handling-exceptions-within-postgresql-transactions\">\n<h3>Traitement des exceptions dans les transactions PostgreSQL<a class=\"heading-anchor\" href=\"#handling-exceptions-within-postgresql-transactions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Cette section n’a de sens que si vous implémentez votre propre gestion des transactions. Ce problème ne peut pas survenir dans le mode par défaut de Django et <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> s’en charge automatiquement.</p>\n</aside>\n<p>À l’intérieur d’une transaction, lorsque l’appel à un curseur PostgreSQL génère une exception (typiquement <code class=\"docutils literal notranslate\"><span class=\"pre\">IntegrityError</span></code>), toutes les commandes SQL suivantes dans la même transaction échouent avec l’erreur « current transaction is aborted, queries ignored until end of transaction block ». Bien qu’il soit improbable qu’une utilisation simple de <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> génère une exception avec PostgreSQL, il y a des schémas d’utilisation plus pointus qui sont susceptibles de le faire, comme l’enregistrement d’objets avec des champs uniques, l’enregistrement avec les options <code class=\"docutils literal notranslate\"><span class=\"pre\">force_insert</span></code>/<code class=\"docutils literal notranslate\"><span class=\"pre\">force_update</span></code> ou l’appel à des instructions SQL personnalisées.</p>\n<p>Il existe plusieurs manières de se sortir de ce genre d’erreurs.</p>\n<section id=\"transaction-rollback\">\n<h4>Annulation de la transaction<a class=\"heading-anchor\" href=\"#transaction-rollback\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>La première option est d’annuler la totalité de la transaction. Par exemple :</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=\"n\">a</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, but may be undone by transaction rollback</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"n\">b</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Could throw exception</span>\n<span class=\"k\">except</span> <span class=\"n\">IntegrityError</span><span class=\"p\">:</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">rollback</span><span class=\"p\">()</span>\n<span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, but a.save() may have been undone</span>\n</code></pre></div>\n<p>L’appel de <code class=\"docutils literal notranslate\"><span class=\"pre\">transaction.rollback()</span></code> annule la totalité de la transaction. Toute opération de base de données non validée sera perdue. Dans cet exemple, les modifications effectuées par <code class=\"docutils literal notranslate\"><span class=\"pre\">a.save()</span></code> seront perdues, même si cette opération n’a pas elle-même généré d’erreur.</p>\n</section>\n<section id=\"savepoint-rollback\">\n<h4>Annulation du point de sauvegarde<a class=\"heading-anchor\" href=\"#savepoint-rollback\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Vous pouvez utiliser des <a class=\"reference internal\" href=\"#topics-db-transactions-savepoints\"><span class=\"std std-ref\">points de sauvegarde</span></a> pour contrôler l’étendue d’une annulation. Avant d’effectuer une opération de base de données potentiellement délicate, vous pouvez définir ou mettre à jour le point de sauvegarde ; de cette façon, si l’opération échoue, vous pouvez annuler précisément l’opération concernée, plutôt que la totalité de la transaction. Par exemple :</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=\"n\">a</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, and never undone by savepoint rollback</span>\n<span class=\"n\">sid</span> <span class=\"o\">=</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint</span><span class=\"p\">()</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"n\">b</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Could throw exception</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_commit</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n<span class=\"k\">except</span> <span class=\"n\">IntegrityError</span><span class=\"p\">:</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_rollback</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n<span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, and a.save() is never undone</span>\n</code></pre></div>\n<p>Dans cet exemple, <code class=\"docutils literal notranslate\"><span class=\"pre\">a.save()</span></code> ne sera pas annulé dans le cas où <code class=\"docutils literal notranslate\"><span class=\"pre\">b.save()</span></code> génère une exception.</p>\n</section>\n</section>\n</section>","rootId":"module-django.db.transaction","toc":[{"title":"Gestion des transactions de base de données","anchor":"managing-database-transactions","children":[{"title":"Comportement de transaction par défaut de Django","anchor":"django-s-default-transaction-behavior","children":[]},{"title":"Couplage des transactions aux requêtes HTTP","anchor":"tying-transactions-to-http-requests","children":[]},{"title":"Contrôle explicite des transactions","anchor":"controlling-transactions-explicitly","children":[]}]},{"title":"Autocommit","anchor":"autocommit","children":[{"title":"Pourquoi Django utilise-t-il l’autocommit","anchor":"why-django-uses-autocommit","children":[]},{"title":"Désactivation de la gestion des transaction","anchor":"deactivating-transaction-management","children":[]}]},{"title":"Lancement d’actions après le commit","anchor":"performing-actions-after-commit","children":[{"title":"Points de sauvegarde (« savepoints »)","anchor":"savepoints","children":[]},{"title":"Ordre d’exécution","anchor":"order-of-execution","children":[]},{"title":"Gestion des exceptions","anchor":"exception-handling","children":[]},{"title":"Ordre d’exécution","anchor":"timing-of-execution","children":[]},{"title":"Utilisation dans les tests","anchor":"use-in-tests","children":[]},{"title":"Pourquoi pas de point d’entrée pour les transactions annulées ?","anchor":"why-no-rollback-hook","children":[]}]},{"title":"API de bas niveau","anchor":"low-level-apis","children":[{"title":"Autocommit","anchor":"managing-autocommit","children":[]},{"title":"Transactions","anchor":"transactions","children":[]},{"title":"Points de sauvegarde (« savepoints »)","anchor":"topics-db-transactions-savepoints","children":[]}]},{"title":"Notes spécifiques à certaines bases de données","anchor":"database-specific-notes","children":[{"title":"Points de sauvegarde dans","anchor":"savepoints-in-sqlite","children":[]},{"title":"Transactions dans MySQL","anchor":"transactions-in-mysql","children":[]},{"title":"Traitement des exceptions dans les transactions PostgreSQL","anchor":"handling-exceptions-within-postgresql-transactions","children":[{"title":"Annulation de la transaction","anchor":"transaction-rollback","children":[]},{"title":"Annulation du point de sauvegarde","anchor":"savepoint-rollback","children":[]}]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/1.11/topics/"},{"docname":"topics/db/index","title":"Modèles et bases de données","url":"/fr/1.11/topics/db/"}],"prev":{"docname":"topics/db/sql","title":"Lancement de requêtes SQL brutes","url":"/fr/1.11/topics/db/sql/"},"next":{"docname":"topics/db/multi-db","title":"Bases de données multiples","url":"/fr/1.11/topics/db/multi-db/"},"formats":{"html":"/fr/1.11/topics/db/transactions/","markdown":"/fr/1.11/topics/db/transactions.md","json":"/fr/1.11/topics/db/transactions.json"},"source":"https://github.com/django/django/blob/stable/1.11.x/docs/topics/db/transactions.txt","official":"https://docs.djangoproject.com/fr/1.11/topics/db/transactions/","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","1.11","1.10","1.9"],"inLocales":["en","fr","ja","id","pt-br","ko","es","el","pl"]}