{"title":"Bases de données","version":"3.0","locale":"fr","docname":"ref/databases","url":"/fr/3.0/ref/databases/","canonical":"https://djangodocs.dev/fr/3.0/ref/databases/","summary":"Django prend officiellement en charge les bases de données suivantes : PostgreSQL MariaDB MySQL Oracle SQLite Il existe également un certain nombre de moteurs de…","html":"<h1>Bases de données<a class=\"heading-anchor\" href=\"#databases\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django prend officiellement en charge les bases de données suivantes :</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"#postgresql-notes\"><span class=\"std std-ref\">PostgreSQL</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#mariadb-notes\"><span class=\"std std-ref\">MariaDB</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#mysql-notes\"><span class=\"std std-ref\">MySQL</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#oracle-notes\"><span class=\"std std-ref\">Oracle</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#sqlite-notes\"><span class=\"std std-ref\">SQLite</span></a></p></li>\n</ul>\n<p>Il existe également un certain nombre de <a class=\"reference internal\" href=\"#third-party-notes\"><span class=\"std std-ref\">moteurs de base de données fournis par des sources tierces</span></a>.</p>\n<p>Django tente d’activer autant de fonctionnalités que possible sur tous les types de base de données. Cependant, tous les types de base de données ne sont pas semblables, et nous avons dû prendre des décisions de conception sur les fonctionnalités à activer et les hypothèses sur lesquelles nous pouvions nous baser en toute sécurité.</p>\n<p>Ce fichier décrit quelques-unes des caractéristiques qui pourraient être pertinentes pour l’utilisation de Django. Bien sûr, il ne remplace pas la documentation ou les manuels de référence spécifiques aux différents serveurs de base de données.</p>\n<section id=\"general-notes\">\n<h2>Remarques générales<a class=\"heading-anchor\" href=\"#general-notes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"persistent-connections\">\n<span id=\"persistent-database-connections\"></span><h3>Connexions persistantes<a class=\"heading-anchor\" href=\"#persistent-connections\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les connexions persistantes évitent de devoir rétablir une connexion à la base de données pour chaque requête. Elles sont contrôlées par le réglage <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> qui définit la durée de vie maximale d’une connexion. Ce réglage peut être défini indépendamment pour chaque base de données.</p>\n<p>La valeur par défaut est <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>, pour préserver le comportement historique de la fermeture de la connexion de base de données à la fin de chaque requête. Pour activer les connexions persistantes, définissez <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> à un nombre entier positif de secondes. Pour que les connexions persistantes soient illimitées dans le temps, définissez-le à <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>.</p>\n<section id=\"connection-management\">\n<h4>Gestion des connexions<a class=\"heading-anchor\" href=\"#connection-management\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Django ouvre une connexion à la base de données lors de la première requête de base de données. Il garde cette connexion ouverte et la réutilise pour les requêtes suivantes. Django ferme la connexion dès que la limite de durée définie par <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> est dépassée ou que la connexion n’est plus utilisable.</p>\n<p>Dans le détail, Django ouvre automatiquement une connexion à la base de données chaque fois qu’il en a besoin et qu’il n’en a pas déjà une – soit parce que c’est la première connexion, soit parce que la connexion précédente a été fermée.</p>\n<p>Avant chaque requête à la base de données, Django clôture la connexion si celle-ci a atteint la limite de durée. Si votre base de données termine les connexions inactives après une certaine durée, vous devez définir <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> à une valeur inférieure, de sorte que Django ne cherche pas à utiliser une connexion qui a été interrompue par le serveur de base de données (ce problème ne peut affecter que les sites à très faible trafic).</p>\n<p>À la fin de chaque requête à la base de données, Django clôture la connexion si celle-ci a atteint la limite de durée ou si elle est dans un état d’erreur irrécupérable. Si des erreurs de base de données ont eu lieu lors du traitement des requêtes, Django vérifie si la connexion fonctionne encore, et la ferme si ce n’est pas le cas. De cette manière, les erreurs de base de données affectent au plus une requête ; si la connexion devient inutilisable, la prochaine requête obtient une nouvelle connexion.</p>\n</section>\n<section id=\"caveats\">\n<h4>Mises en garde<a class=\"heading-anchor\" href=\"#caveats\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Comme chaque fil d’exécution gère sa propre connexion, la base de données doit prendre en charge au moins autant de connexions simultanées qu’il n’y a de fils d’exécution (threads) de travail pour Django.</p>\n<p>Parfois, la majorité des vues n’accèdent pas à une certaine base de données, par exemple parce que c’est la base de données d’un système externe, ou grâce à la mise en cache. Dans ce cas, vous devez définir <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-CONN_MAX_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CONN_MAX_AGE</span></code></a> à une valeur faible, voire à <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>, car cela n’a aucun sens de maintenir une connexion qui est peu susceptible d’être réutilisée. Cela contribuera à garder un petit nombre de connexions simultanées à cette base de données.</p>\n<p>Le serveur de développement crée un nouveau fil d’exécution pour chaque requête qu’il gère, annulant l’effet des connexions persistantes. Ne les activez pas pendant le développement.</p>\n<p>Lorsque Django établit une connexion à la base de données, il met en place les paramètres appropriés en fonction du type de base de données utilisé. Si vous activez les connexions persistantes, cette phase de configuration n’est pas répétée pour chaque requête. Si vous modifiez des paramètres tels que le niveau d’isolement de la connexion ou le fuseau horaire, vous devez soit restaurer les paramètres par défaut de Django à la fin de chaque requête, soit forcer une valeur appropriée avant chaque requête, soit désactiver les connexions persistantes.</p>\n</section>\n</section>\n<section id=\"encoding\">\n<h3>Codage de caractères<a class=\"heading-anchor\" href=\"#encoding\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django suppose que toutes les bases de données utilisent le codage UTF-8. L’utilisation d’autres codages peut entraîner un comportement inattendu comme des erreurs de base de données « valeur trop longue » pour des données qui sont valides dans Django. Consultez les notes ci-dessous spécifiques à chaque base de données pour obtenir des informations sur la façon de configurer correctement votre base de données.</p>\n</section>\n</section>\n<section id=\"postgresql-notes\">\n<span id=\"id1\"></span><h2>Notes sur PostgreSQL<a class=\"heading-anchor\" href=\"#postgresql-notes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django prend en charge PostgreSQL 9.5 et plus récent. <a class=\"reference external\" href=\"https://www.psycopg.org/\">psycopg2</a> 2.5.4 ou plus récent est requis, même s’il est recommandé d’utiliser la version la plus récente.</p>\n<section id=\"postgresql-connection-settings\">\n<h3>Paramètres de connexion PostgreSQL<a class=\"heading-anchor\" href=\"#postgresql-connection-settings\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Voir <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> pour plus de détails.</p>\n</section>\n<section id=\"optimizing-postgresql-s-configuration\">\n<h3>Optimisation de la configuration de PostgreSQL<a class=\"heading-anchor\" href=\"#optimizing-postgresql-s-configuration\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django a besoin des paramètres suivants pour se connecter aux bases de données :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">client_encoding</span></code>: <code class=\"docutils literal notranslate\"><span class=\"pre\">'UTF8'</span></code>,</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">default_transaction_isolation</span></code>: <code class=\"docutils literal notranslate\"><span class=\"pre\">'read</span> <span class=\"pre\">committed'</span></code> par défaut, ou la valeur définie dans les options de connexion (voir ci-dessous),</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">timezone</span></code>: <code class=\"docutils literal notranslate\"><span class=\"pre\">'UTC'</span></code> quand <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-USE_TZ\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USE_TZ</span></code></a> vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>, sinon indiquez la valeur de <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-TIME_ZONE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code></a>.</p></li>\n</ul>\n<p>Si ces paramètres ont déjà les valeurs correctes, Django n’aura pas à les indiquer pour chaque nouvelle connexion, ce qui améliore légèrement les performances. Vous pouvez les configurer directement dans <code class=\"file docutils literal notranslate\"><span class=\"pre\">postgresql.conf</span></code> ou plus commodément pour chaque utilisateur de base de données avec <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/sql-alterrole.html\">ALTER ROLE</a>.</p>\n<p>Django fonctionne très bien sans cette optimisation, mais chaque nouvelle connexion va faire quelques requêtes supplémentaires pour définir ces paramètres.</p>\n</section>\n<section id=\"isolation-level\">\n<span id=\"database-isolation-level\"></span><h3>Niveau d’isolement<a class=\"heading-anchor\" href=\"#isolation-level\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme pour PostgreSQL lui-même, le <a href=\"#id16\"><span class=\"problematic\" id=\"id17\">`niveau d'isolement`_</span></a> de Django vaut par défaut <code class=\"docutils literal notranslate\"><span class=\"pre\">READ</span> <span class=\"pre\">COMMITTED</span></code>. Si vous avez besoin d’un plus haut niveau d’isolement tel que <code class=\"docutils literal notranslate\"><span class=\"pre\">REPEATABLE</span> <span class=\"pre\">READ</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">SERIALIZABLE</span></code>, définissez-le dans la partie <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> de la configuration de base de données <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</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\">import</span><span class=\"w\"> </span><span class=\"nn\">psycopg2.extensions</span>\n\n<span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;isolation_level&#39;</span><span class=\"p\">:</span> <span class=\"n\">psycopg2</span><span class=\"o\">.</span><span class=\"n\">extensions</span><span class=\"o\">.</span><span class=\"n\">ISOLATION_LEVEL_SERIALIZABLE</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Sous des niveaux d’isolement plus élevés, votre application doit être préparée à gérer des exceptions générées lors d’échecs de sérialisation. Cette option est prévue pour des utilisateurs avancés.</p>\n</aside>\n</section>\n<section id=\"indexes-for-varchar-and-text-columns\">\n<h3>Index pour les colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">varchar</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code><a class=\"heading-anchor\" href=\"#indexes-for-varchar-and-text-columns\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque vous indiquez  <code class=\"docutils literal notranslate\"><span class=\"pre\">db_index=True</span></code> sur vos champs de modèle, Django génère généralement un seul <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">INDEX</span></code>. Toutefois, si le type de champ de base de données est <code class=\"docutils literal notranslate\"><span class=\"pre\">varchar</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> (par exemple, pour les champs de type <code class=\"docutils literal notranslate\"><span class=\"pre\">CharField</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">FileField</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code>), Django crée alors un index supplémentaire qui utilise une <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/indexes-opclass.html\">classe opérateur de PostgreSQL</a> appropriée pour la colonne. Cet index supplémentaire est nécessaire pour le bon fonctionnement des recherches qui utilisent l’opérateur SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">LIKE</span></code>, comme le font les recherches avec <code class=\"docutils literal notranslate\"><span class=\"pre\">contains</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">startswith</span></code>.</p>\n</section>\n<section id=\"migration-operation-for-adding-extensions\">\n<h3>Opération de migration pour ajouter des extensions<a class=\"heading-anchor\" href=\"#migration-operation-for-adding-extensions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si vous avez besoin d’ajouter une extension PostgreSQL (comme <code class=\"docutils literal notranslate\"><span class=\"pre\">hstore</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">postgis</span></code>, etc.) en utilisant une migration, utilisez l’opération <a class=\"reference internal\" href=\"/fr/3.0/ref/contrib/postgres/operations/#django.contrib.postgres.operations.CreateExtension\" title=\"django.contrib.postgres.operations.CreateExtension\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CreateExtension</span></code></a>.</p>\n</section>\n<section id=\"server-side-cursors\">\n<span id=\"postgresql-server-side-cursors\"></span><h3>Curseurs côté serveur<a class=\"heading-anchor\" href=\"#server-side-cursors\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsqu’on utilise <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#django.db.models.query.QuerySet.iterator\" title=\"django.db.models.query.QuerySet.iterator\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">QuerySet.iterator()</span></code></a>, Django ouvre un <a class=\"reference external\" href=\"https://www.psycopg.org/docs/usage.html#server-side-cursors\" title=\"(disponible dans Psycopg v2.9)\"><span class=\"xref std std-ref\">curseur côté serveur</span></a>. Par défaut, PostgreSQL suppose que seuls les premiers 10% des résultats des requêtes de curseur seront récupérées. Le planificateur de requête passe moins de temps à planifier la requête et commence à renvoyer des résultats plus rapidement, mais cela peut aussi diminuer les performances si plus de 10% des résultats sont récupérés. Les suppositions de PostgreSQL sur le nombre de lignes récupérées d’une requête de curseur sont contrôlées par l’option <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-CURSOR-TUPLE-FRACTION\">cursor_tuple_fraction</a>.</p>\n<section id=\"transaction-pooling-and-server-side-cursors\">\n<span id=\"transaction-pooling-server-side-cursors\"></span><h4>Transactions groupées et curseurs côté serveur<a class=\"heading-anchor\" href=\"#transaction-pooling-and-server-side-cursors\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>L’utilisation d’un concentrateur (pooler) de connexion en mode groupement de transactions (par ex. <a class=\"reference external\" href=\"https://pgbouncer.github.io/\">PgBouncer</a>) nécessite de désactiver les curseurs côté serveur pour cette connexion.</p>\n<p>Les curseurs côté serveur sont propres à une connexion et restent ouverts à la fin d’une transaction lorsque <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-DATABASE-AUTOCOMMIT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTOCOMMIT</span></code></a> vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>. Une prochaine transaction peut demander l’obtention de davantage de résultats de la part du curseur côté serveur. En mode groupement de transactions, il n’y a aucune garantie que les transactions suivantes réutilisent la même connexion. Si une autre connexion est utilisée, une erreur survient lorsque la transaction fait référence au curseur côté serveur, car ces types de curseurs ne sont accessibles que pour la connexion dans laquelle ils ont été créés.</p>\n<p>Une solution est de désactiver les curseurs côté serveur pour une connexion dans <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> en définissant <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-DATABASE-DISABLE_SERVER_SIDE_CURSORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DISABLE_SERVER_SIDE_CURSORS</span></code></a> à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>.</p>\n<p>Pour bénéficier des curseurs côté serveur en mode de groupement des transactions, il est possible de définir une <a class=\"reference internal\" href=\"/fr/3.0/topics/db/multi-db/\"><span class=\"doc\">autre connexion à la base de données</span></a> afin d’effectuer des requêtes utilisant les curseurs côté serveur. Cette connexion doit se faire soit directement à la base de données soit vers un concentrateur de connexions en mode de groupement par session.</p>\n<p>Une autre option est d’envelopper chaque <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> utilisant des curseurs côté serveur dans un bloc <a class=\"reference internal\" href=\"/fr/3.0/topics/db/transactions/#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>, car ceci désactive le mode <code class=\"docutils literal notranslate\"><span class=\"pre\">autocommit</span></code> pour la durée de la transaction. De cette façon, le curseur côté serveur ne sera actif que pour la durée de la transaction.</p>\n</section>\n</section>\n<section id=\"manually-specifying-values-of-auto-incrementing-primary-keys\">\n<span id=\"manually-specified-autoincrement-pk\"></span><h3>Indication manuelle des valeurs de clé primaire avec autoincrémentation<a class=\"heading-anchor\" href=\"#manually-specifying-values-of-auto-incrementing-primary-keys\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django utilise le <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL\">type de données SERIAL</a> de PostgreSQL pour stocker les clés primaires autoincrémentées. Une colonne <code class=\"docutils literal notranslate\"><span class=\"pre\">SERIAL</span></code> est remplie par des valeurs d’une <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/sql-createsequence.html\">séquence</a> qui garde la trace de la prochaine valeur disponible. L’attribution manuelle d’une valeur à un champ autoincrémenté ne met pas à jour la séquence du champ, ce qui peut causer un conflit plus tard. 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=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">User</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s1\">&#39;alice&#39;</span><span class=\"p\">,</span> <span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;User: alice&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># The sequence hasn&#39;t been updated; its next value is 1.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s1\">&#39;bob&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">...</span>\n<span class=\"go\">IntegrityError: duplicate key value violates unique constraint</span>\n<span class=\"go\">&quot;auth_user_pkey&quot; DETAIL:  Key (id)=(1) already exists.</span>\n</code></pre></div>\n<p>Si vous devez indiquer de telles valeurs, réinitialisez ensuite la séquence pour éviter de réutiliser une valeur qui se trouve déjà dans la table. La commande d’administration <a class=\"reference internal\" href=\"/fr/3.0/ref/django-admin/#django-admin-sqlsequencereset\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">sqlsequencereset</span></code></a> génère les commandes SQL qui font cela.</p>\n</section>\n<section id=\"test-database-templates\">\n<h3>Modèles de base de données de test<a class=\"heading-anchor\" href=\"#test-database-templates\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>On peut utiliser le réglage <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-TEST_TEMPLATE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TEST['TEMPLATE']</span></code></a> pour indiquer un <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/sql-createdatabase.html\">modèle</a> (par ex. <code class=\"docutils literal notranslate\"><span class=\"pre\">'template0'</span></code>) à partir duquel la base de données de test est créée.</p>\n</section>\n<section id=\"speeding-up-test-execution-with-non-durable-settings\">\n<h3>Accélération de l’exécution des tests par des réglages temporaires<a class=\"heading-anchor\" href=\"#speeding-up-test-execution-with-non-durable-settings\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Vous pouvez accélérer l’exécution des tests en <a class=\"reference external\" href=\"http://docs.postgresql.fr/11/non-durability.html\">configurant PostgreSQL avec perte acceptée</a>.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>C’est dangereux : votre base de données sera plus sujette aux pertes de données ou aux corruptions dans le case de plantage de serveur ou de coupure de courant. N’utilisez cela que sur des machines de développement où vous pouvez facilement restaurer l’ensemble de toutes les bases de données dans la grappe (cluster).</p>\n</aside>\n</section>\n</section>\n<section id=\"mariadb-notes\">\n<span id=\"id3\"></span><h2>Notes MariaDB<a class=\"heading-anchor\" href=\"#mariadb-notes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<aside class=\"version-note version-added\" data-version=\"3.0\">\n<p class=\"version-note-title\">New in Django 3.0</p></aside>\n<p>Django prend en charge les versions 10.1 et plus récentes de MariaDB.</p>\n<p>Pour utiliser MariaDB, employez le moteur MySQL qui est partagé entre les deux. Consultez les <a class=\"reference internal\" href=\"#mysql-notes\"><span class=\"std std-ref\">notes MySQL</span></a> pour plus de détails.</p>\n</section>\n<section id=\"mysql-notes\">\n<span id=\"id4\"></span><h2>Notes sur MySQL<a class=\"heading-anchor\" href=\"#mysql-notes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"version-support\">\n<h3>Versions prises en charge<a class=\"heading-anchor\" href=\"#version-support\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django prend en charge les versions 5.6 et plus récentes de MySQL.</p>\n<p>La fonctionnalité <code class=\"docutils literal notranslate\"><span class=\"pre\">inspectdb</span></code> de Django utilise la base de données <code class=\"docutils literal notranslate\"><span class=\"pre\">information_schema</span></code>, qui contient des données détaillées sur tous les schémas de la base de données.</p>\n<p>Django s’attend à ce que la base de données accepte l’Unicode (codage UTF-8) et lui délègue la charge de faire respecter les transactions et l’intégrité référentielle. Il est important d’être conscient du fait que ces deux derniers aspects ne sont pas réellement appliqués par MySQL lorsque le moteur de stockage MyISAM est utilisé, voir la section suivante.</p>\n</section>\n<section id=\"storage-engines\">\n<span id=\"mysql-storage-engines\"></span><h3>Les moteurs de stockage<a class=\"heading-anchor\" href=\"#storage-engines\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>MySQL possède plusieurs <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/storage-engines.html\">moteurs de stockage</a>. Vous pouvez changer le moteur de stockage par défaut dans la configuration du serveur.</p>\n<p>Le moteur de stockage par défaut de MySQL est <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html\">InnoDB</a>. Ce moteur est pleinement transactionnel et prend en charge les références de clé étrangère. Il s’agit du choix recommandé. Cependant, le compteur d’incrémentation automatique de InnoDB est perdu au redémarrage de MySQL car il ne conserve pas la valeur <code class=\"docutils literal notranslate\"><span class=\"pre\">AUTO_INCREMENT</span></code> mais la recalcule comme « max(id)+1 ». Cela peut aboutir à une réutilisation inappropriée de valeurs <a class=\"reference internal\" href=\"/fr/3.0/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AutoField</span></code></a>.</p>\n<p>Les désavantages principaux de <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/myisam-storage-engine.html\">MyISAM</a> sont qu’il ne prend pas en charge les transactions et ne vérifie pas les contraintes de clé étrangère.</p>\n</section>\n<section id=\"mysql-db-api-drivers\">\n<span id=\"id6\"></span><h3>Pilotes DB API MySQL<a class=\"heading-anchor\" href=\"#mysql-db-api-drivers\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>MySQL propose plusieurs pilotes qui implémentent l’API Python de base de données documentée dans <span class=\"target\" id=\"index-2\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a>:</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference external\" href=\"https://pypi.org/project/mysqlclient/\">mysqlclient</a> est un pilote natif. Il s’agit du <strong>choix recommandé</strong>.</p></li>\n<li><p><a class=\"reference external\" href=\"https://dev.mysql.com/downloads/connector/python\">MySQL Connector/Python</a> est un pilote en Python pur écrit par Oracle qui n’a pas besoin de la bibliothèque client MySQL ni d’autres modules Python en dehors de la bibliothèque standard.</p></li>\n</ul>\n<p>Ces pilotes respectent la concurrence entre fils d’exécution (thread-safe) et gèrent le regroupement de connexions (pooling).</p>\n<p>En plus d’un pilote DB API, Django a besoin d’un adaptateur pour accéder aux pilotes de bases de données à partir de son ORM. Django fournit un adaptateur pour mysqlclient alors que MySQL Connector/Python inclut le <a class=\"reference external\" href=\"https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html\">sien</a>.</p>\n<section id=\"id7\">\n<h4>mysqlclient<a class=\"heading-anchor\" href=\"#id7\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Django nécessite la version 1.3.13 ou ultérieure de <a class=\"reference external\" href=\"https://pypi.org/project/mysqlclient/\">mysqlclient</a>.</p>\n</section>\n<section id=\"id8\">\n<h4>MySQL Connector/Python<a class=\"heading-anchor\" href=\"#id8\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>MySQL Connector/Python est disponible sur cette <a class=\"reference external\" href=\"https://dev.mysql.com/downloads/connector/python/\">page de téléchargement</a>. L’adaptateur Django est disponible dans les versions 1.1.X et ultérieures. Il est possible qu’il ne prenne pas en charge la toute dernière version de Django.</p>\n</section>\n</section>\n<section id=\"time-zone-definitions\">\n<span id=\"mysql-time-zone-definitions\"></span><h3>Définitions de fuseaux horaires<a class=\"heading-anchor\" href=\"#time-zone-definitions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si vous prévoyez d’utiliser la <a class=\"reference internal\" href=\"/fr/3.0/topics/i18n/timezones/\"><span class=\"doc\">prise en charge des fuseaux horaires</span></a> de Django, utilisez <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/mysql-tzinfo-to-sql.html\">mysql_tzinfo_to_sql</a> pour charger les tableaux de fuseaux horaires dans la base de données MySQL. Cela doit être fait une seule fois par serveur MySQL, pas pour chaque base de données.</p>\n</section>\n<section id=\"creating-your-database\">\n<h3>Création d’une base de données<a class=\"heading-anchor\" href=\"#creating-your-database\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Vous pouvez <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/create-database.html\">créer une base de données</a> à l’aide des outils de ligne de commande et de cette commande SQL :</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\">CREATE</span> <span class=\"n\">DATABASE</span> <span class=\"o\">&lt;</span><span class=\"n\">dbname</span><span class=\"o\">&gt;</span> <span class=\"n\">CHARACTER</span> <span class=\"n\">SET</span> <span class=\"n\">utf8</span><span class=\"p\">;</span>\n</code></pre></div>\n<p>Cela garantit que toutes les tables et colonnes utilisent le codage UTF-8 par défaut.</p>\n<section id=\"collation-settings\">\n<span id=\"mysql-collation\"></span><h4>Paramètres de tri<a class=\"heading-anchor\" href=\"#collation-settings\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>La méthode de tri (« collation ») d’une colonne détermine l’ordre dans lequel les données sont triées ainsi que les comparaisons d’égalité entre les chaînes. Ce paramètre peut être défini à l’échelle de la base de données mais aussi par table et par colonne. Ceci est <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/charset.html\">documenté complètement</a> dans la documentation MySQL. Dans tous les cas, la méthode de tri est définie en modifiant directement les tables de la base de données ; Django ne fournit aucun moyen de faire cela au niveau de la définition du modèle.</p>\n<p>Par défaut, avec une base de données UTF-8, MySQL utilise la collation <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_general_ci</span></code>. En conséquence, toutes les comparaisons d’égalité de chaînes se fait de manière insensible à la casse. C’est-à-dire que « Fred » et « freD » sont jugés équivalents pour la base de données. Si vous avez placé une contrainte unique sur un champ, il ne serait pas permis d’insérer à la fois « aa » et « AA » dans cette même colonne, dans la mesure où leur comparaison dit qu’elles sont identiques (et donc pas uniques) avec la collation par défaut. Si vous souhaitez effectuer des comparaisons sensibles à la casse sur une colonne ou table particulière, modifiez la collation de la colonne ou table en <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_bin</span></code>.</p>\n<p>Notez que selon les <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/charset-unicode-sets.html\">Jeux de caractères Unicode MySQL</a>, les comparaisons avec la collation <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_general_ci</span></code> sont plus rapides, mais légèrement moins correctes que les comparaisons avec <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_unicode_ci</span></code>. Si cela est acceptable pour votre application, il est préférable d’utiliser <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_general_ci</span></code> car elle est plus rapide. Dans le cas contraire (par exemple si vous avez besoin de l’ordre du dictionnaire allemand), utilisez <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_unicode_ci</span></code> car cette collation est plus juste.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Les sous-formulaires de modèles valident les champs uniques de manière sensible à la casse. Ainsi, lors de l’utilisation d’une collation de base de données insensible à la casse, des sous-formulaires contenant des valeurs de champs uniques qui ne diffèrent que par leur casse vont passer la validation avec succès, mais au moment de l’enregistrement par <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code>, une exception <code class=\"docutils literal notranslate\"><span class=\"pre\">IntegrityError</span></code> va se produire.</p>\n</aside>\n</section>\n</section>\n<section id=\"connecting-to-the-database\">\n<h3>Connexion à la base de données<a class=\"heading-anchor\" href=\"#connecting-to-the-database\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Reportez-vous à la <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/\"><span class=\"doc\">documentation des réglages</span></a>.</p>\n<p>Les paramètres de connexion sont utilisés dans cet ordre :</p>\n<ol class=\"arabic simple\">\n<li><p><a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a>, <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-USER\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USER</span></code></a>, <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-PASSWORD\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD</span></code></a>, <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a>,\n<a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a></p></li>\n<li><p>Fichiers d’options de MySQL.</p></li>\n</ol>\n<p>En d’autres termes, si vous définissez le nom de la base de données dans <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a>, cette définition a la priorité sur <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a>, qui aurait lui-même la priorité sur n’importe quelle valeur d’un <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/option-files.html\">fichier d’options MySQL</a>.</p>\n<p>Voici un exemple de configuration qui utilise un fichier d’options MySQL :</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=\"c1\"># settings.py</span>\n<span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;read_default_file&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;/path/to/my.cnf&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n\n\n<span class=\"c1\"># my.cnf</span>\n<span class=\"p\">[</span><span class=\"n\">client</span><span class=\"p\">]</span>\n<span class=\"n\">database</span> <span class=\"o\">=</span> <span class=\"n\">NAME</span>\n<span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">USER</span>\n<span class=\"n\">password</span> <span class=\"o\">=</span> <span class=\"n\">PASSWORD</span>\n<span class=\"n\">default</span><span class=\"o\">-</span><span class=\"n\">character</span><span class=\"o\">-</span><span class=\"nb\">set</span> <span class=\"o\">=</span> <span class=\"n\">utf8</span>\n</code></pre></div>\n<p>Quelques autres <a class=\"reference external\" href=\"https://mysqlclient.readthedocs.io/user_guide.html#functions-and-attributes\">options de connexion MySQLdb</a> peuvent se révéler utiles, telles que <code class=\"docutils literal notranslate\"><span class=\"pre\">ssl</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">init_command</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code>.</p>\n<section id=\"setting-sql-mode\">\n<span id=\"mysql-sql-mode\"></span><h4>Définition de <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code><a class=\"heading-anchor\" href=\"#setting-sql-mode\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>À partir de MySQL 5.7 et pour les nouvelles installations de MySQL 5.6, la valeur par défaut de l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code> contient <code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_TRANS_TABLES</span></code>. Cette option transforme les avertissements en erreurs lorsque des données sont tronquées lors de leur insertion. Django recommande fortement d’activer un <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/sql-mode.html#sql-mode-strict\">mode strict</a> pour MySQL afin d’éviter des pertes de données (<code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_TRANS_TABLES</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_ALL_TABLES</span></code>).</p>\n<p>SI vous avez besoin de personnaliser le mode SQL, vuos pouvez définir la variable <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code> comme toute autre option MySQL : soit dans un fichier de configuration, soit par la ligne <code class=\"docutils literal notranslate\"><span class=\"pre\">'init_command':</span> <span class=\"pre\">&quot;SET</span> <span class=\"pre\">sql_mode='STRICT_TRANS_TABLES'&quot;</span></code> dans la partie <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> de la configuration de base de données dans <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a>.</p>\n</section>\n<section id=\"mysql-isolation-level\">\n<span id=\"id9\"></span><h4>Niveau d’isolement<a class=\"heading-anchor\" href=\"#mysql-isolation-level\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Lors d’un fonctionnement avec charge concurrentielle, les transactions de base de données de différentes sessions (par exemple des fils d’exécution séparés traitant différentes requêtes) peuvent interagir entre elles. Ces interactions sont affectées par le <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/innodb-transaction-isolation-levels.html\">niveau d’isolation de transaction</a> de chaque session. Il est possible de définir le niveau d’isolation de transaction d’une connexion avec la clé <code class=\"docutils literal notranslate\"><span class=\"pre\">'isolation_level'</span></code> de la partie <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> de la configuration de base de données dans <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a>. Les valeurs autorisées pour cette clé sont les quatre niveaux d’isolation standards :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'read</span> <span class=\"pre\">uncommitted'</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'read</span> <span class=\"pre\">committed'</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'repeatable</span> <span class=\"pre\">read'</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">'serializable'</span></code></p></li>\n</ul>\n<p>ou <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> pour utiliser le niveau d’isolation configuré sur le serveur. Cependant, Django fonctionne mieux avec <code class=\"docutils literal notranslate\"><span class=\"pre\">read</span> <span class=\"pre\">committed</span></code> (choix Django par défaut) plutôt que la valeur par défaut de MySQL qui est <code class=\"docutils literal notranslate\"><span class=\"pre\">repeatable</span> <span class=\"pre\">read</span></code>. Des pertes de données sont possibles avec le niveau <code class=\"docutils literal notranslate\"><span class=\"pre\">repeatable</span> <span class=\"pre\">read</span></code>. En particulier, vous pouvez rencontrer des cas où <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#django.db.models.query.QuerySet.get_or_create\" title=\"django.db.models.query.QuerySet.get_or_create\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_or_create()</span></code></a> génère une exception <a class=\"reference internal\" href=\"/fr/3.0/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> mais l’objet n’apparaît pas dans de futurs appels à <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a>.</p>\n</section>\n</section>\n<section id=\"creating-your-tables\">\n<h3>Création des tables<a class=\"heading-anchor\" href=\"#creating-your-tables\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque Django génère le schéma, il ne précise pas de moteur de stockage, donc les tables seront créées avec le moteur de stockage par défaut de votre serveur de base de données. La solution la plus simple est de définir le moteur souhaité comme moteur de stockage par défaut pour votre serveur de base de données.</p>\n<p>Si vous utilisez un service d’hébergement et que vous ne pouvez pas modifier le moteur de stockage par défaut sur votre serveur, vous avez plusieurs possibilités.</p>\n<ul>\n<li><p>Après la création des tables, exécutez une commande SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">ALTER</span> <span class=\"pre\">TABLE</span></code> pour convertir une table vers un nouveau moteur de stockage (comme InnoDB) :</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\">ALTER</span> <span class=\"n\">TABLE</span> <span class=\"o\">&lt;</span><span class=\"n\">tablename</span><span class=\"o\">&gt;</span> <span class=\"n\">ENGINE</span><span class=\"o\">=</span><span class=\"n\">INNODB</span><span class=\"p\">;</span>\n</code></pre></div>\n<p>Cela peut être fastidieux si vous avez beaucoup de tables.</p>\n</li>\n<li><p>Une autre possibilité est d’utiliser l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">init_command</span></code> de MySQLdb avant de créer les tables :</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=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n   <span class=\"s1\">&#39;init_command&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;SET default_storage_engine=INNODB&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>Ceci définit le moteur de stockage par défaut lors de la connexion à la base de données. Une fois que les tables ont été créées, vous devriez supprimer cette option car elle ajoute une requête lors de chaque connexion à la base de données, alors que c’est uniquement nécessaire lors de la création d’une table.</p>\n</li>\n</ul>\n</section>\n<section id=\"table-names\">\n<h3>Noms de tables<a class=\"heading-anchor\" href=\"#table-names\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Certains <a class=\"reference external\" href=\"https://bugs.mysql.com/bug.php?id=48875\">problèmes connus</a>, même dans les dernières versions de MySQL peuvent engendrer une modification d’un nom de table lorsque certaines instructions SQL sont exécutées sous certaines conditions. Il est recommandé d’utiliser des noms de table en minuscules, si possible, pour éviter les problèmes qui pourraient résulter de ce comportement. Django utilise des noms de tables en minuscules quand il génère automatiquement les noms de table à partir des modèles, c’est donc un élément à prendre en compte surtout si vous surchargez le nom de la table en utilisant le paramètre <a class=\"reference internal\" href=\"/fr/3.0/ref/models/options/#django.db.models.Options.db_table\" title=\"django.db.models.Options.db_table\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">db_table</span></code></a>.</p>\n</section>\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>L’ORM de Django tout comme MySQL (lorsque le <a class=\"reference internal\" href=\"#mysql-storage-engines\"><span class=\"std std-ref\">moteur de stockage</span></a> InnoDB est utilisé) prennent en charge les <a class=\"reference internal\" href=\"/fr/3.0/topics/db/transactions/#topics-db-transactions-savepoints\"><span class=\"std std-ref\">points de sauvegarde</span></a> des bases de données.</p>\n<p>Si vous utilisez le moteur de stockage MyISAM, vous recevrez des erreurs générées par la base de données si vous essayez d’utiliser les <a class=\"reference internal\" href=\"/fr/3.0/topics/db/transactions/#topics-db-transactions-savepoints\"><span class=\"std std-ref\">méthodes de l’API des transactions liées aux points de sauvegarde</span></a>.  En effet, comme la détection du moteur de stockage d’une table ou d’une base de données MySQL est une opération très coûteuse en ressources, il a été décidé de ne pas convertir dynamiquement ces méthodes en méthodes neutres en se basant sur ce genre de détection.</p>\n</section>\n<section id=\"notes-on-specific-fields\">\n<h3>Notes sur des champs particuliers<a class=\"heading-anchor\" href=\"#notes-on-specific-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<section id=\"character-fields\">\n<h4>Champs de type caractère<a class=\"heading-anchor\" href=\"#character-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Tous les champs qui sont stockés dans des types de colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">VARCHAR</span></code> ont leur taille maximale (<code class=\"docutils literal notranslate\"><span class=\"pre\">max_length</span></code>) limitée à 255 caractères si vous utilisez <code class=\"docutils literal notranslate\"><span class=\"pre\">unique=True</span></code> pour ce champ. Cela concerne les champs <a class=\"reference internal\" href=\"/fr/3.0/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.0/ref/models/fields/#django.db.models.SlugField\" title=\"django.db.models.SlugField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SlugField</span></code></a>.</p>\n</section>\n<section id=\"textfield-limitations\">\n<h4>Limites des champs<a class=\"heading-anchor\" href=\"#textfield-limitations\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>MySQL ne peut indexer que les N premiers caractères d’une colonne <code class=\"docutils literal notranslate\"><span class=\"pre\">BLOB</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">TEXT</span></code>. Comme <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> n’a pas de longueur définie, il n’est pas possible de marquer un tel champ avec <code class=\"docutils literal notranslate\"><span class=\"pre\">unique=True</span></code>. MySQL produirait l’erreur : « BLOB/TEXT column “&lt;db_column&gt;” used in key specification without a key length ».</p>\n</section>\n<section id=\"fractional-seconds-support-for-time-and-datetime-fields\">\n<span id=\"mysql-fractional-seconds\"></span><h4>Prise en charge des fractions de secondes pour les champs heure et date/heure<a class=\"heading-anchor\" href=\"#fractional-seconds-support-for-time-and-datetime-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>À partir de la version 5.6.4, MySQL est capable de stocker des fractions de secondes, pour autant que les définitions de colonnes contiennent une indication adéquate (par ex.  <code class=\"docutils literal notranslate\"><span class=\"pre\">DATETIME(6)</span></code>). Dans les versions précédentes, ce n’était pas pris en charge du tout.</p>\n<p>Django ne va pas mettre à jour lui-même les colonnes existantes pour que les fractions de secondes soient incluses si le serveur de base de données le prend en charge. Si vous souhaitez les activer dans une base de données existante, c’est à vous de mettre à jour la colonne manuellement dans la base de données en exécutant une commande du style :</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>ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)\n</code></pre></div>\n<p>ou en utilisant une opération <a class=\"reference internal\" href=\"/fr/3.0/ref/migration-operations/#django.db.migrations.operations.RunSQL\" title=\"django.db.migrations.operations.RunSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RunSQL</span></code></a> dans une <a class=\"reference internal\" href=\"/fr/3.0/topics/migrations/#data-migrations\"><span class=\"std std-ref\">migration de données</span></a>.</p>\n</section>\n<section id=\"timestamp-columns\">\n<h4>Colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">TIMESTAMP</span></code><a class=\"heading-anchor\" href=\"#timestamp-columns\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Si vous utilisez une base de données existante qui contient des colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">TIMESTAMP</span></code>, vous devez définir <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-USE_TZ\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USE_TZ</span> <span class=\"pre\">=</span> <span class=\"pre\">False</span></code></a> pour éviter de corrompre des données. <a class=\"reference internal\" href=\"/fr/3.0/ref/django-admin/#django-admin-inspectdb\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">inspectdb</span></code></a> fait correspondre ces colonnes à des champs <a class=\"reference internal\" href=\"/fr/3.0/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a> et si vous activez la prise en charge des fuseaux horaires, aussi bien MySQL que Django vont tenter de convertir les valeurs depuis le fuseau UTC vers le temps local.</p>\n</section>\n</section>\n<section id=\"row-locking-with-queryset-select-for-update\">\n<h3>Verrouillage de ligne avec <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.select_for_update()</span></code><a class=\"heading-anchor\" href=\"#row-locking-with-queryset-select-for-update\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>MySQL et MariaDB ne gèrent pas certaines options de l’instruction <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">...</span> <span class=\"pre\">FOR</span> <span class=\"pre\">UPDATE</span></code>. Si <code class=\"docutils literal notranslate\"><span class=\"pre\">select_for_update()</span></code> est utilisé avec une option non prise en charge, une exception <a class=\"reference internal\" href=\"/fr/3.0/ref/exceptions/#django.db.NotSupportedError\" title=\"django.db.NotSupportedError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">NotSupportedError</span></code></a> est générée.</p>\n<div class=\"table-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"Table\"><table class=\"docutils align-default\">\n<thead>\n<tr class=\"row-odd\"><th class=\"head\"><p>Option</p></th>\n<th class=\"head\"><p>MariaDB</p></th>\n<th class=\"head\"><p>MySQL</p></th>\n</tr>\n</thead>\n<tbody>\n<tr class=\"row-even\"><td><p><code class=\"docutils literal notranslate\"><span class=\"pre\">SKIP</span> <span class=\"pre\">LOCKED</span></code></p></td>\n<td></td>\n<td><p>X (≥8.0.1)</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><code class=\"docutils literal notranslate\"><span class=\"pre\">NOWAIT</span></code></p></td>\n<td><p>X (≥10.3)</p></td>\n<td><p>X (≥8.0.1)</p></td>\n</tr>\n<tr class=\"row-even\"><td><p><code class=\"docutils literal notranslate\"><span class=\"pre\">OF</span></code></p></td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Lors de l’utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">select_for_update()</span></code> avec MySQL, assurez-vous de filtrer la requête avec au moins un champ contenu dans les contraintes d’unicité ou uniquement avec des champs dotés d’index. Sinon, un verrou exclusif en écriture sera acquis pour toute la table durant toute la transaction.</p>\n</section>\n<section id=\"automatic-typecasting-can-cause-unexpected-results\">\n<h3>Le retypage automatique peut produire des résultats inattendus<a class=\"heading-anchor\" href=\"#automatic-typecasting-can-cause-unexpected-results\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lors de l’exécution d’une requête sur un type chaîne mais avec une valeur nombre entier, MySQL force les types de toutes les valeurs de la table à des nombres entiers avant d’effectuer la comparaison. Si la table contient les valeurs <code class=\"docutils literal notranslate\"><span class=\"pre\">'abc'</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">'def'</span></code> et que la requête cherche <code class=\"docutils literal notranslate\"><span class=\"pre\">WHERE</span> <span class=\"pre\">macolonne=0</span></code>, les deux lignes vont correspondre. De la même manière, <code class=\"docutils literal notranslate\"><span class=\"pre\">WHERE</span> <span class=\"pre\">macolonne=1</span></code> correspond à la valeur <code class=\"docutils literal notranslate\"><span class=\"pre\">'abc1'</span></code>. C’est pourquoi les champs de type chaîne inclus dans Django forcent toujours la valeur à une chaîne avant de l’utiliser dans une requête.</p>\n<p>Si vous implémentez des champs de modèle personnalisés héritant directement de <a class=\"reference internal\" href=\"/fr/3.0/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a>, que vous surchargez <a class=\"reference internal\" href=\"/fr/3.0/ref/models/fields/#django.db.models.Field.get_prep_value\" title=\"django.db.models.Field.get_prep_value\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_prep_value()</span></code></a> ou que vous utilisez <a class=\"reference internal\" href=\"/fr/3.0/ref/models/expressions/#django.db.models.expressions.RawSQL\" title=\"django.db.models.expressions.RawSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RawSQL</span></code></a>, <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#django.db.models.query.QuerySet.extra\" title=\"django.db.models.query.QuerySet.extra\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">extra()</span></code></a> ou <a class=\"reference internal\" href=\"/fr/3.0/topics/db/sql/#django.db.models.Manager.raw\" title=\"django.db.models.Manager.raw\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">raw()</span></code></a>, vous devez vous assurer d’effectuer les forçages de type appropriés.</p>\n</section>\n</section>\n<section id=\"sqlite-notes\">\n<span id=\"id10\"></span><h2>Notes sur SQLite<a class=\"heading-anchor\" href=\"#sqlite-notes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django prend en charge les versions 3.8.3 et plus récentes de SQLite.</p>\n<p><a class=\"reference external\" href=\"https://www.sqlite.org/\">SQLite</a> fournit une excellente alternative pour le développement d’applications qui sont essentiellement en lecture seule ou qui nécessitent une installation de plus petite taille. Comme avec tous les serveurs de base de données, cependant, il y a quelques différences spécifiques à SQLite à prendre en compte.</p>\n<section id=\"substring-matching-and-case-sensitivity\">\n<span id=\"sqlite-string-matching\"></span><h3>Recherche de portions de chaînes de caractères et sensibilité à la casse<a class=\"heading-anchor\" href=\"#substring-matching-and-case-sensitivity\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour toutes les versions de SQLite, il y a un comportement peu intuitif lorsque l’on essaie de faire correspondre certains types de chaînes. Ce comportement est déclenché lors de l’utilisation des filtres <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#std-fieldlookup-iexact\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">iexact</span></code></a> ou <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#std-fieldlookup-contains\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">contains</span></code></a> dans des QuerySets. Le comportement se divise en deux cas :</p>\n<p>1. For substring matching, all matches are done case-insensitively. That is a\nfilter such as <code class=\"docutils literal notranslate\"><span class=\"pre\">filter(name__contains=&quot;aa&quot;)</span></code> will match a name of <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;Aabb&quot;</span></code>.</p>\n<p>2. For strings containing characters outside the ASCII range, all exact string\nmatches are performed case-sensitively, even when the case-insensitive options\nare passed into the query. So the <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#std-fieldlookup-iexact\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">iexact</span></code></a> filter will behave exactly\nthe same as the <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#std-fieldlookup-exact\"><code class=\"xref std std-lookup docutils literal notranslate\"><span class=\"pre\">exact</span></code></a> filter in these cases.</p>\n<p>Il existe quelques solutions de contournement <a class=\"reference external\" href=\"https://www.sqlite.org/faq.html#q18\">documentées sur sqlite.org</a>, mais elles ne sont pas exploitées par le moteur SQLite par défaut de Django, car cela impliquerait des difficultés certaines pour le faire de manière robuste. Django présente donc le comportement SQLite par défaut et il faut en être bien conscient lors de filtrage de sous-chaînes ou de chaînes insensibles à la casse.</p>\n</section>\n<section id=\"decimal-handling\">\n<span id=\"sqlite-decimal-handling\"></span><h3>Gestion des nombres décimaux<a class=\"heading-anchor\" href=\"#decimal-handling\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>SQLite n’a pas vraiment de type nombre décimal en interne. Les valeurs décimales sont converties dans le type de données <code class=\"docutils literal notranslate\"><span class=\"pre\">REAL</span></code> (nombre à virgule flottante 8-octets IEEE), comme présenté dans la <a class=\"reference external\" href=\"https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes\">documentation des types de données SQLite</a>, ce qui explique pourquoi l’arithmétique sur des nombres décimaux à virgule flottante n’est pas géré correctement (problèmes d’arrondis).</p>\n</section>\n<section id=\"database-is-locked-errors\">\n<h3>Erreurs « Database is locked » (la base de données est verrouillée)<a class=\"heading-anchor\" href=\"#database-is-locked-errors\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>SQLite est supposé être une base de données légère et ne peut donc pas gérer un niveau élevé de concurrence. Les erreurs <code class=\"docutils literal notranslate\"><span class=\"pre\">OperationalError:</span> <span class=\"pre\">database</span> <span class=\"pre\">is</span> <span class=\"pre\">locked</span></code> indiquent que l’application subit une concurrence plus élevée que ce que <code class=\"docutils literal notranslate\"><span class=\"pre\">sqlite</span></code> ne peut gérer dans sa configuration par défaut. Cette erreur signifie qu’un processus ou un fil d’exécution possède un verrou exclusif sur la connexion de base de données et qu’un autre fil d’exécution a dû attendre trop longtemps que le verrou se libère.</p>\n<p>L’adaptateur SQLite de Python comporte une valeur d’expiration par défaut qui détermine le temps maximal d’attente de déverrouillage d’un autre fil d’exécution avant qu’il n’expire en générant une erreur <code class=\"docutils literal notranslate\"><span class=\"pre\">OperationalError:</span> <span class=\"pre\">database</span> <span class=\"pre\">is</span> <span class=\"pre\">locked</span></code>.</p>\n<p>Si vous obtenez cette erreur, vous pouvez résoudre le problème en :</p>\n<ul>\n<li><p>Passant à un autre moteur de base de données. À un certain stade, SQLite devient vraiment trop léger pour des applications du monde réel, et ce type d’erreur de concurrence indique que ce point a été atteint.</p></li>\n<li><p>Réécrivant le code pour réduire la concurrence et s’assurer que les transactions de base de données restent aussi brèves que possible.</p></li>\n<li><p>Augmentant la valeur d’expiration par défaut en définissant l’option de base de données <code class=\"docutils literal notranslate\"><span class=\"pre\">timeout</span></code>:</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=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"s1\">&#39;timeout&#39;</span><span class=\"p\">:</span> <span class=\"mi\">20</span><span class=\"p\">,</span>\n    <span class=\"c1\"># ...</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>Cela prolongera un peu le temps d’attente de SQLite avant de produire des erreurs « database is locked » ; mais le problème de base n’en est pas résolu pour autant.</p>\n</li>\n</ul>\n</section>\n<section id=\"queryset-select-for-update-not-supported\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.select_for_update()</span></code> non pris en charge<a class=\"heading-anchor\" href=\"#queryset-select-for-update-not-supported\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>SQLite ne prend pas en charge la syntaxe <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">...</span> <span class=\"pre\">FOR</span> <span class=\"pre\">UPDATE</span></code>. L’appel de cette méthode n’a aucun effet.</p>\n</section>\n<section id=\"pyformat-parameter-style-in-raw-queries-not-supported\">\n<h3>Le style de paramètre « pyformat » dans les requêtes brutes n’est pas pris en charge<a class=\"heading-anchor\" href=\"#pyformat-parameter-style-in-raw-queries-not-supported\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour la plupart des moteurs, les requêtes brutes (<code class=\"docutils literal notranslate\"><span class=\"pre\">Manager.raw()</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">cursor.execute()</span></code>) peuvent exploiter le style de paramètre « pyformat » où les substituants dans la requête sont écrits sous la forme <code class=\"docutils literal notranslate\"><span class=\"pre\">'%(nom)s'</span></code> et les paramètres sont transmis sous forme de dictionnaire au lieu de liste. SQLite ne prend pas cette syntaxe en charge.</p>\n</section>\n<section id=\"isolation-when-using-queryset-iterator\">\n<span id=\"sqlite-isolation\"></span><h3>Isolation lors de l’utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.iterator()</span></code><a class=\"heading-anchor\" href=\"#isolation-when-using-queryset-iterator\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il existe des situations spéciales décrites dans <a class=\"reference external\" href=\"https://sqlite.org/isolation.html\">Isolation dans SQLite</a> lorsqu’on modifie une table tout en la parcourant avec <a class=\"reference internal\" href=\"/fr/3.0/ref/models/querysets/#django.db.models.query.QuerySet.iterator\" title=\"django.db.models.query.QuerySet.iterator\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">QuerySet.iterator()</span></code></a>. Si une ligne est ajoutée, modifiée ou détruite dans la boucle, cette ligne peut apparaître ou non, ou même apparaître deux fois dans les résultats suivants en provenance de l’itérateur. Votre code doit gérer cela.</p>\n</section>\n</section>\n<section id=\"oracle-notes\">\n<span id=\"id12\"></span><h2>Notes sur Oracle<a class=\"heading-anchor\" href=\"#oracle-notes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django prend en charge les versions 12.2 et plus récentes du <a class=\"reference external\" href=\"https://www.oracle.com/\">serveur de base de données Oracle</a>. Il est nécessaire de posséder au minimum la version 6.0 du pilote Python <a class=\"reference external\" href=\"https://oracle.github.io/python-cx_Oracle/\">cx_Oracle</a>.</p>\n<p>Pour que la commande <code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code> fonctionne, l’utilisateur de base de données Oracle doit posséder les permissions d’exécuter les commandes suivantes :</p>\n<ul class=\"simple\">\n<li><p>CREATE TABLE</p></li>\n<li><p>CREATE SEQUENCE</p></li>\n<li><p>CREATE PROCEDURE</p></li>\n<li><p>CREATE TRIGGER</p></li>\n</ul>\n<p>Pour exécuter la suite de tests d’un projet, l’utilisateur doit généralement posséder les privilèges <em>supplémentaires</em> suivants :</p>\n<ul class=\"simple\">\n<li><p>CREATE USER</p></li>\n<li><p>ALTER USER</p></li>\n<li><p>DROP USER</p></li>\n<li><p>CREATE TABLESPACE</p></li>\n<li><p>DROP TABLESPACE</p></li>\n<li><p>CREATE SESSION WITH ADMIN OPTION</p></li>\n<li><p>CREATE TABLE WITH ADMIN OPTION</p></li>\n<li><p>CREATE SEQUENCE WITH ADMIN OPTION</p></li>\n<li><p>CREATE PROCEDURE WITH ADMIN OPTION</p></li>\n<li><p>CREATE TRIGGER WITH ADMIN OPTION</p></li>\n</ul>\n<p>Même si le rôle <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span></code> possède les privilèges requis <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TABLE</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">SEQUENCE</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">PROCEDURE</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TRIGGER</span></code>, et qu’un utilisateur disposant de <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code> peut accorder le privilège <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span></code>, cet utilisateur ne peut pas accorder de privilèges individuels (par ex. <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TABLE</span></code>), ce qui fait que <code class=\"docutils literal notranslate\"><span class=\"pre\">RESOURCE</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code> n’est généralement pas suffisant pour exécuter les tests.</p>\n<p>Certaines suites de tests créent aussi des vues ou des vues matérialisées ; pour exécuter celles-ci, l’utilisateur a aussi besoin des privilèges <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">VIEW</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">MATERIALIZED</span> <span class=\"pre\">VIEW</span> <span class=\"pre\">WITH</span> <span class=\"pre\">ADMIN</span> <span class=\"pre\">OPTION</span></code>. C’est nécessaire en particulier pour la propre suite de tests de Django.</p>\n<p>Tous ces privilèges sont inclus dans le rôle DBA, qui est adéquat dans le cadre d’une base de données de développement privée.</p>\n<p>Le moteur de base de données Oracle utilise les paquets <code class=\"docutils literal notranslate\"><span class=\"pre\">SYS.DBMS_LOB</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">SYS.DBMS_RANDOM</span></code>, il faut donc que l’utilisateur possède les droits d’exécution pour lui. Il est normalement accessible par défaut à tous les utilisateurs, mais si ce n’est pas le cas, il faut attribuer les permissions comme ceci :</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">GRANT</span><span class=\"w\"> </span><span class=\"k\">EXECUTE</span><span class=\"w\"> </span><span class=\"k\">ON</span><span class=\"w\"> </span><span class=\"n\">SYS</span><span class=\"p\">.</span><span class=\"n\">DBMS_LOB</span><span class=\"w\"> </span><span class=\"k\">TO</span><span class=\"w\"> </span><span class=\"k\">user</span><span class=\"p\">;</span>\n<span class=\"k\">GRANT</span><span class=\"w\"> </span><span class=\"k\">EXECUTE</span><span class=\"w\"> </span><span class=\"k\">ON</span><span class=\"w\"> </span><span class=\"n\">SYS</span><span class=\"p\">.</span><span class=\"n\">DBMS_RANDOM</span><span class=\"w\"> </span><span class=\"k\">TO</span><span class=\"w\"> </span><span class=\"k\">user</span><span class=\"p\">;</span>\n</code></pre></div>\n<section id=\"id13\">\n<h3>Connexion à la base de données<a class=\"heading-anchor\" href=\"#id13\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour se connecter en utilisant le nom de service de la base de données Oracle, le fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> doit ressembler à quelque chose 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=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.oracle&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;xe&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;a_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;a_password&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;HOST&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PORT&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>Dans ce cas, il faut laisser vide les deux clés <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a>. Cependant, si vous n’utilisez pas de fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">tnsnames.ora</span></code> ou une méthode de nommage similaire et que vous vouliez vous connecter en utilisant le SID (« xe » dans cet exemple), remplissez alors à la fois <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a>, 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=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.oracle&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;xe&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;a_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;a_password&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;HOST&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;dbprod01ned.mycompany.com&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PORT&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;1540&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>Il faut soit remplir les deux clés <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a>, soit les laisser toutes deux vides. Django utilise un descripteur de connexion différent en fonction de ce choix.</p>\n<section id=\"full-dsn-and-easy-connect\">\n<h4>DSN complet et Easy Connect<a class=\"heading-anchor\" href=\"#full-dsn-and-easy-connect\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Un chaîn DSN complète ou Easy Connect peut être utilisée dans <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a> si à la fois <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-PORT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PORT</span></code></a> sont vides. Ce format est requis par exemple lors de l’utilisation de RAC ou de bases de données enfichables sans <code class=\"docutils literal notranslate\"><span class=\"pre\">tnsnames.ora</span></code>.</p>\n<p>Exemple d’une chaîne Easy Connect</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=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;localhost:1521/orclpdb1&#39;</span><span class=\"p\">,</span>\n</code></pre></div>\n<p>Exemple d’une chaîne DSN complète</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=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span>\n    <span class=\"s1\">&#39;(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))&#39;</span>\n    <span class=\"s1\">&#39;(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))&#39;</span>\n<span class=\"p\">),</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"threaded-option\">\n<h3>Option threaded<a class=\"heading-anchor\" href=\"#threaded-option\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si vous prévoyez de faire fonctionner Django dans un environnement à fils d’exécution multiples (multithread), par exemple avec Apache et le module MPM par défaut sur tout système d’exploitation moderne), vous <strong>devez</strong> définir à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">threaded</span></code> de votre configuration de base de données Oracle :</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=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;threaded&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n<span class=\"p\">},</span>\n</code></pre></div>\n<p>Si vous ne le faites pas, vous risquez d’obtenir des plantées et d’autres comportements bizarres.</p>\n</section>\n<section id=\"insert-returning-into\">\n<h3>INSERT … RETURNING INTO<a class=\"heading-anchor\" href=\"#insert-returning-into\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Par défaut, le moteur Oracle utilise une clause <code class=\"docutils literal notranslate\"><span class=\"pre\">RETURNING</span> <span class=\"pre\">INTO</span></code> pour obtenir efficacement la valeur d’un champ <code class=\"docutils literal notranslate\"><span class=\"pre\">AutoField</span></code> lors de l’insertion de nouvelles lignes. Ce comportement peut aboutir à des erreurs <code class=\"docutils literal notranslate\"><span class=\"pre\">DatabaseError</span></code> dans certaines configurations particulières, comme lors de l’insertion dans une table distante ou dans une vue avec le déclencheur <code class=\"docutils literal notranslate\"><span class=\"pre\">INSTEAD</span> <span class=\"pre\">OF</span></code>. La clause <code class=\"docutils literal notranslate\"><span class=\"pre\">RETURNING</span> <span class=\"pre\">INTO</span></code> peut être désactivée en définissant l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">use_returning_into</span></code> de la configuration de base de données à <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>:</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=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;use_returning_into&#39;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n<span class=\"p\">},</span>\n</code></pre></div>\n<p>Dans ce cas, le moteur Oracle utilise une requête <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span></code> séparée pour récupérer les valeurs <code class=\"docutils literal notranslate\"><span class=\"pre\">AutoField</span></code>.</p>\n</section>\n<section id=\"naming-issues\">\n<h3>Questions de nommage<a class=\"heading-anchor\" href=\"#naming-issues\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Oracle impose une longueur limite de 30 caractères pour les noms. Pour respecter cela, le moteur tronque les identifiants de base de données si nécessaire, remplaçant les quatre caractères finaux du nom tronqué par une valeur de hachage MD5 reproductible. De plus, le moteur transforme les identifiants de base de données tout en majuscules.</p>\n<p>Pour empêcher ces transformations (ce qui n’est généralement nécessaire que lorsqu’on a affaire à des bases de données existantes ou quand il faut accéder à des tables appartenant à d’autres utilisateurs), entourez la valeur de <code class=\"docutils literal notranslate\"><span class=\"pre\">db_table</span></code> par des guillemets :</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\">class</span><span class=\"w\"> </span><span class=\"nc\">LegacyModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">db_table</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;&quot;name_left_in_lowercase&quot;&#39;</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">ForeignModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">db_table</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;&quot;OTHER_USER&quot;.&quot;NAME_ONLY_SEEMS_OVER_30&quot;&#39;</span>\n</code></pre></div>\n<p>Les noms entre guillemets peuvent également être utilisés avec les autres moteurs de base de données pris en charge par Django ; mais ces guillemets n’ont un effet qu’avec Oracle.</p>\n<p>Lors de l’exécution de <code class=\"docutils literal notranslate\"><span class=\"pre\">migrate</span></code>, une erreur <code class=\"docutils literal notranslate\"><span class=\"pre\">ORA-06552</span></code> peut se produire si certains mots-clés Oracle sont employés comme noms de champs de modèle ou comme valeur de l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">db_column</span></code>. Django place entre guillemets tous les identifiants utilisés dans les requêtes pour empêcher la plupart de ce genre de problèmes, mais cette erreur peut quand même se produire lorsqu’un type de données Oracle est utilisé comme nom de colonne. Plus particulièrement, essayez d’éviter d’utiliser les noms <code class=\"docutils literal notranslate\"><span class=\"pre\">date</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">timestamp</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">number</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">float</span></code> comme noms de champs.</p>\n</section>\n<section id=\"null-and-empty-strings\">\n<span id=\"oracle-null-empty-strings\"></span><h3>NULL et les chaînes vides<a class=\"heading-anchor\" href=\"#null-and-empty-strings\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django préfère généralement utiliser la chaîne vide (<code class=\"docutils literal notranslate\"><span class=\"pre\">''</span></code>) plutôt que <code class=\"docutils literal notranslate\"><span class=\"pre\">NULL</span></code>, mais Oracle considère ces deux valeurs comme identiques. Pour contourner cela, le moteur Oracle ignore l’option explicite <code class=\"docutils literal notranslate\"><span class=\"pre\">null</span></code> pour les champs où la chaîne vide est une valeur possible et génère les instructions SQL comme si <code class=\"docutils literal notranslate\"><span class=\"pre\">null=True</span></code>. Lors de la lecture à partir de la base de données, Django part du principe qu’une valeur <code class=\"docutils literal notranslate\"><span class=\"pre\">NULL</span></code> dans l’un de ces champs équivaut en réalité à la chaîne vide et les données sont silencieusement converties pour respecter ce principe.</p>\n</section>\n<section id=\"id14\">\n<h3>Limites des champs<a class=\"heading-anchor\" href=\"#id14\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le moteur Oracle stocke les champs <code class=\"docutils literal notranslate\"><span class=\"pre\">TextFields</span></code> dans des colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">NCLOB</span></code>. Oracle impose certaines limites à l’utilisation de telles colonnes LOB en général :</p>\n<ul class=\"simple\">\n<li><p>Les colonnes LOB ne peuvent pas être utilisées comme clés primaires.</p></li>\n<li><p>Les colonnes LOB ne peuvent pas être utilisées dans les index.</p></li>\n<li><p>Les colonnes LOB ne peuvent pas être utilisées dans une liste <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">DISTINCT</span></code>. Cela signifie qu’une tentative d’utiliser la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.distinct</span></code> pour un modèle qui contient des colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> produira une erreur <code class=\"docutils literal notranslate\"><span class=\"pre\">ORA-00932``avec</span> <span class=\"pre\">Oracle.</span> <span class=\"pre\">Pour</span> <span class=\"pre\">contourner</span> <span class=\"pre\">ce</span> <span class=\"pre\">problème,</span> <span class=\"pre\">utilisez</span> <span class=\"pre\">la</span> <span class=\"pre\">méthode</span> <span class=\"pre\">``QuerySet.defer</span></code> de concert avec <code class=\"docutils literal notranslate\"><span class=\"pre\">distinct()</span></code> afin d’éviter que des colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code> ne se retrouvent incluses dans la liste <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">DISTINCT</span></code>.</p></li>\n</ul>\n</section>\n</section>\n<section id=\"subclassing-the-built-in-database-backends\">\n<span id=\"subclassing-database-backends\"></span><h2>Création de sous-classe d’un moteur de base de données intégré<a class=\"heading-anchor\" href=\"#subclassing-the-built-in-database-backends\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django est livré avec des moteurs de base de données intégrés. Il est possible d’en créer des sous-classes pour modifier leur comportement, leurs fonctionnalités ou leur configuration.</p>\n<p>Imaginez par exemple que vous deviez modifier une seule fonctionnalité de base de données. Premièrement, il s’agit de créer un nouveau répertoire contenant un module <code class=\"docutils literal notranslate\"><span class=\"pre\">base</span></code>. 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\">mysite</span><span class=\"o\">/</span>\n    <span class=\"o\">...</span>\n    <span class=\"n\">mydbengine</span><span class=\"o\">/</span>\n        <span class=\"fm\">__init__</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">base</span><span class=\"o\">.</span><span class=\"n\">py</span>\n</code></pre></div>\n<p>Le module <code class=\"docutils literal notranslate\"><span class=\"pre\">base.py</span></code> doit contenir une classe nommée <code class=\"docutils literal notranslate\"><span class=\"pre\">DatabaseWrapper</span></code> qui hérite d’un moteur existant à partir du module <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.backends</span></code>. Voici un exemple d’une sous-classe du moteur PostgreSQL dans le but de modifier une fonctionnalité de classe <code class=\"docutils literal notranslate\"><span class=\"pre\">allows_group_by_selected_pks_on_model</span></code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">monsite/mydbengine/base.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.backends.postgresql</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">base</span><span class=\"p\">,</span> <span class=\"n\">features</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">DatabaseFeatures</span><span class=\"p\">(</span><span class=\"n\">features</span><span class=\"o\">.</span><span class=\"n\">DatabaseFeatures</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">allows_group_by_selected_pks_on_model</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"kc\">True</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">DatabaseWrapper</span><span class=\"p\">(</span><span class=\"n\">base</span><span class=\"o\">.</span><span class=\"n\">DatabaseWrapper</span><span class=\"p\">):</span>\n    <span class=\"n\">features_class</span> <span class=\"o\">=</span> <span class=\"n\">DatabaseFeatures</span>\n</code></pre></figure>\n<p>Pour terminer, vous devez indiquer une valeur <a class=\"reference internal\" href=\"/fr/3.0/ref/settings/#std-setting-DATABASE-ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASE-ENGINE</span></code></a> dans votre fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code>:</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\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mydbengine&#39;</span><span class=\"p\">,</span>\n        <span class=\"o\">...</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>Vous pouvez voir la liste actuelle des moteurs de base de données en examinant le répertoire <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/stable/3.0.x/django/db/backends\">django/db/backends</a>.</p>\n</section>\n<section id=\"using-a-3rd-party-database-backend\">\n<span id=\"third-party-notes\"></span><h2>Utilisation d’un moteur de base de données externe<a class=\"heading-anchor\" href=\"#using-a-3rd-party-database-backend\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>En plus des bases de données prises en charge officiellement, il existe des moteurs externes à Django qui permettent d’utiliser d’autres bases de données avec Django :</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference external\" href=\"https://pypi.org/project/django-cockroachdb/\">CockroachDB</a></p></li>\n<li><p><a class=\"reference external\" href=\"https://pypi.org/project/django-firebird/\">Firebird</a></p></li>\n<li><p><a class=\"reference external\" href=\"https://pypi.org/project/django-mssql-backend/\">Microsoft SQL Server</a></p></li>\n</ul>\n<p>Les versions de Django et les fonctionnalités ORM prises en charges par ces moteurs inofficiels varient considérablement. Si vous avez des questions concernant les capacités spécifiques de ces moteurs inofficiels ou des questions de support, vous devrez vous adresser aux canaux d’aide offerts par chacun de ces projets externes.</p>\n</section>","rootId":"databases","toc":[{"title":"Remarques générales","anchor":"general-notes","children":[{"title":"Connexions persistantes","anchor":"persistent-connections","children":[{"title":"Gestion des connexions","anchor":"connection-management","children":[]},{"title":"Mises en garde","anchor":"caveats","children":[]}]},{"title":"Codage de caractères","anchor":"encoding","children":[]}]},{"title":"Notes sur PostgreSQL","anchor":"postgresql-notes","children":[{"title":"Paramètres de connexion PostgreSQL","anchor":"postgresql-connection-settings","children":[]},{"title":"Optimisation de la configuration de PostgreSQL","anchor":"optimizing-postgresql-s-configuration","children":[]},{"title":"Niveau d’isolement","anchor":"isolation-level","children":[]},{"title":"Index pour les colonnes varchar et text","anchor":"indexes-for-varchar-and-text-columns","children":[]},{"title":"Opération de migration pour ajouter des extensions","anchor":"migration-operation-for-adding-extensions","children":[]},{"title":"Curseurs côté serveur","anchor":"server-side-cursors","children":[{"title":"Transactions groupées et curseurs côté serveur","anchor":"transaction-pooling-and-server-side-cursors","children":[]}]},{"title":"Indication manuelle des valeurs de clé primaire avec autoincrémentation","anchor":"manually-specifying-values-of-auto-incrementing-primary-keys","children":[]},{"title":"Modèles de base de données de test","anchor":"test-database-templates","children":[]},{"title":"Accélération de l’exécution des tests par des réglages temporaires","anchor":"speeding-up-test-execution-with-non-durable-settings","children":[]}]},{"title":"Notes MariaDB","anchor":"mariadb-notes","children":[]},{"title":"Notes sur MySQL","anchor":"mysql-notes","children":[{"title":"Versions prises en charge","anchor":"version-support","children":[]},{"title":"Les moteurs de stockage","anchor":"storage-engines","children":[]},{"title":"Pilotes DB API MySQL","anchor":"mysql-db-api-drivers","children":[{"title":"mysqlclient","anchor":"id7","children":[]},{"title":"MySQL Connector/Python","anchor":"id8","children":[]}]},{"title":"Définitions de fuseaux horaires","anchor":"time-zone-definitions","children":[]},{"title":"Création d’une base de données","anchor":"creating-your-database","children":[{"title":"Paramètres de tri","anchor":"collation-settings","children":[]}]},{"title":"Connexion à la base de données","anchor":"connecting-to-the-database","children":[{"title":"Définition de sql_mode","anchor":"setting-sql-mode","children":[]},{"title":"Niveau d’isolement","anchor":"mysql-isolation-level","children":[]}]},{"title":"Création des tables","anchor":"creating-your-tables","children":[]},{"title":"Noms de tables","anchor":"table-names","children":[]},{"title":"Points de sauvegarde (« savepoints »)","anchor":"savepoints","children":[]},{"title":"Notes sur des champs particuliers","anchor":"notes-on-specific-fields","children":[{"title":"Champs de type caractère","anchor":"character-fields","children":[]},{"title":"Limites des champs","anchor":"textfield-limitations","children":[]},{"title":"Prise en charge des fractions de secondes pour les champs heure et date/heure","anchor":"fractional-seconds-support-for-time-and-datetime-fields","children":[]},{"title":"Colonnes TIMESTAMP","anchor":"timestamp-columns","children":[]}]},{"title":"Verrouillage de ligne avec QuerySet.select_for_update()","anchor":"row-locking-with-queryset-select-for-update","children":[]},{"title":"Le retypage automatique peut produire des résultats inattendus","anchor":"automatic-typecasting-can-cause-unexpected-results","children":[]}]},{"title":"Notes sur SQLite","anchor":"sqlite-notes","children":[{"title":"Recherche de portions de chaînes de caractères et sensibilité à la casse","anchor":"substring-matching-and-case-sensitivity","children":[]},{"title":"Gestion des nombres décimaux","anchor":"decimal-handling","children":[]},{"title":"Erreurs « Database is locked » (la base de données est verrouillée)","anchor":"database-is-locked-errors","children":[]},{"title":"QuerySet.select_for_update() non pris en charge","anchor":"queryset-select-for-update-not-supported","children":[]},{"title":"Le style de paramètre « pyformat » dans les requêtes brutes n’est pas pris en charge","anchor":"pyformat-parameter-style-in-raw-queries-not-supported","children":[]},{"title":"Isolation lors de l’utilisation de QuerySet.iterator()","anchor":"isolation-when-using-queryset-iterator","children":[]}]},{"title":"Notes sur Oracle","anchor":"oracle-notes","children":[{"title":"Connexion à la base de données","anchor":"id13","children":[{"title":"DSN complet et Easy Connect","anchor":"full-dsn-and-easy-connect","children":[]}]},{"title":"Option threaded","anchor":"threaded-option","children":[]},{"title":"INSERT … RETURNING INTO","anchor":"insert-returning-into","children":[]},{"title":"Questions de nommage","anchor":"naming-issues","children":[]},{"title":"NULL et les chaînes vides","anchor":"null-and-empty-strings","children":[]},{"title":"Limites des champs","anchor":"id14","children":[]}]},{"title":"Création de sous-classe d’un moteur de base de données intégré","anchor":"subclassing-the-built-in-database-backends","children":[]},{"title":"Utilisation d’un moteur de base de données externe","anchor":"using-a-3rd-party-database-backend","children":[]}],"breadcrumbs":[{"docname":"ref/index","title":"Référence de l’API","url":"/fr/3.0/ref/"}],"prev":{"docname":"ref/csrf","title":"Protection contre le « Cross site request forgery » (CSRF)","url":"/fr/3.0/ref/csrf/"},"next":{"docname":"ref/django-admin","title":"django-admin et manage.py","url":"/fr/3.0/ref/django-admin/"},"formats":{"html":"/fr/3.0/ref/databases/","markdown":"/fr/3.0/ref/databases.md","json":"/fr/3.0/ref/databases.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/ref/databases.txt","official":"https://docs.djangoproject.com/fr/3.0/ref/databases/","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","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}