{"title":"Bases de données","version":"1.9","locale":"fr","docname":"ref/databases","url":"/fr/1.9/ref/databases/","canonical":"https://djangodocs.dev/fr/1.9/ref/databases/","summary":"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…","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 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/1.9/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/1.9/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 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/1.9/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/1.9/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/1.9/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.1 et plus récent. Il exige la version 2.4.5 ou plus récente de <a class=\"reference external\" href=\"http://initd.org/psycopg/\">psycopg2</a> (ou 2.5+ si vous voulez profiter de <a class=\"reference internal\" href=\"/fr/1.9/ref/contrib/postgres/#module-django.contrib.postgres\" title=\"django.contrib.postgres: PostgreSQL-specific fields and features\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.postgres</span></code></a>).</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/1.9/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/1.9/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/1.9/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=\"http://www.postgresql.org/docs/current/interactive/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 class=\"reference internal\" href=\"#isolation-level\">niveau d’isolement</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/1.9/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/1.9/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=\"http://www.postgresql.org/docs/current/static/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=\"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/9.4/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=\"mysql-notes\">\n<span id=\"id3\"></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.5 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/5.6/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>Jusqu’à MySQL 5.5.4, le moteur par défaut était <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/5.6/en/myisam-storage-engine.html\">MyISAM</a> <a class=\"footnote-reference brackets\" href=\"#id6\" id=\"id4\" role=\"doc-noteref\"><span class=\"fn-bracket\">[</span>1<span class=\"fn-bracket\">]</span></a>. Le principal défaut de MyISAM est qu’il ne prend pas en charge les transactions ni le contrôle des contraintes de clé étrangère. Son aspect positif est qu’il était le seul moteur prenant en charge l’indexation et la recherche plein texte jusqu’à MySQL 5.6.4.</p>\n<p>Depuis MySQL 5.5.5, le moteur de stockage par défaut est <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/5.6/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 probablement du meilleur choix en ce moment. Notez cependant que 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/1.9/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>Si vous mettez à jour un projet existant à MySQL 5.5.5 et que vous y ajoutez de nouvelles tables, vérifiez que toutes les tables utilisent le même moteur de stockage (MyISAM ou InnoDB). En particulier, si des tables impliquées dans une relation de clé étrangère utilisent des moteurs différents, il peut se produire des erreurs comme celle-ci lors de l’exécution de <code class=\"docutils literal notranslate\"><span class=\"pre\">migrate</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\">_mysql_exceptions</span><span class=\"o\">.</span><span class=\"n\">OperationalError</span><span class=\"p\">:</span> <span class=\"p\">(</span>\n    <span class=\"mi\">1005</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Can&#39;t create table &#39;</span><span class=\"se\">\\\\</span><span class=\"s2\">db_name</span><span class=\"se\">\\\\</span><span class=\"s2\">.#sql-4a8_ab&#39; (errno: 150)&quot;</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"footnote-list brackets\">\n<aside class=\"footnote brackets\" id=\"id6\" role=\"doc-footnote\">\n<span class=\"label\"><span class=\"fn-bracket\">[</span><a role=\"doc-backlink\" href=\"#id4\">1</a><span class=\"fn-bracket\">]</span></span>\n<p>À moins que cela n’ait été modifié par le gestionnaire de votre paquet MySQL. Il nous a été rapporté que le programme d’installation de Windows Community Server définit InnoDB comme moteur de stockage par défaut, par exemple.</p>\n</aside>\n</aside>\n</section>\n<section id=\"mysql-db-api-drivers\">\n<span id=\"id7\"></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>L’API de base de données Python est décrite dans la <span class=\"target\" id=\"index-2\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a>. Il y a trois principaux pilotes MySQL implémentant cette API :</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference external\" href=\"https://pypi.python.org/pypi/MySQL-python/1.2.4\">MySQLdb</a> est un pilote natif qui a été développé et maintenu depuis plus de 10 ans par Andy Dustman.</p></li>\n<li><p><a class=\"reference external\" href=\"https://pypi.python.org/pypi/mysqlclient\">mysqlclient</a> est un dérivé de <code class=\"docutils literal notranslate\"><span class=\"pre\">MySQLdb</span></code> qui ajoute la prise en charge de Python 3 et qui peut être utilisé comme remplacement à l’identique de MySQLdb. Au moment d’écrire ces lignes, il s’agit du <strong>choix recommandé</strong> pour utiliser MySQL avec Django.</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>Tous ces pilotes respectent la concurrence entre fils d’exécution (thread-safe) et gèrent le regroupement de connexions. <code class=\"docutils literal notranslate\"><span class=\"pre\">MySQLdb</span></code> est le seul qui ne prend pas encore en charge Python 3.</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 MySQLdb/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=\"id8\">\n<h4>MySQLdb<a class=\"heading-anchor\" href=\"#id8\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Django a besoin de la version 1.2.1p2 ou ultérieure de MySQLdb.</p>\n<p>Au moment d’écrire ces lignes, la version la plus récente de MySQLdb (1.2.5) ne prend pas en charge Python 3. Afin de pouvoir utiliser MySQLdb avec Python 3, il est nécessaire de le remplacer par l’installation de <code class=\"docutils literal notranslate\"><span class=\"pre\">mysqlclient</span></code>.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Il existe des problèmes connus avec la façon dont MySQLdb convertit les chaînes de date en objets <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code>. Plus particulièrement, les chaînes de date contenant la valeur <code class=\"docutils literal notranslate\"><span class=\"pre\">0000-00-00</span></code> sont valables pour MySQL mais sont converties en valeur <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> par MySQLdb.</p>\n<p>Cela signifie que vous devez être prudent lors de l’utilisation de <a class=\"reference internal\" href=\"/fr/1.9/ref/django-admin/#django-admin-loaddata\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">loaddata</span></code></a> et <a class=\"reference internal\" href=\"/fr/1.9/ref/django-admin/#django-admin-dumpdata\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">dumpdata</span></code></a>  avec des lignes qui pourraient contenir des valeurs <code class=\"docutils literal notranslate\"><span class=\"pre\">0000-00-00</span></code>, car elles seront converties en <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>.</p>\n</aside>\n</section>\n<section id=\"id9\">\n<h4>mysqlclient<a class=\"heading-anchor\" href=\"#id9\"><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.3 ou ultérieure de <a class=\"reference external\" href=\"https://pypi.python.org/pypi/mysqlclient\">mysqlclient</a>. Notez que Python 3.2 n’est pas pris en charge. En dehors de la prise en charge de Python 3.3+, mysqlclient devrait se comporter de la même façon que MySQLDB.</p>\n</section>\n<section id=\"id10\">\n<h4>MySQL Connector/Python<a class=\"heading-anchor\" href=\"#id10\"><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/1.9/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/5.6/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/5.6/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/5.6/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.</p>\n<p>Dans de nombreux cas, ce comportement par défaut ne sera pas un problème. Toutefois, si vous voulez vraiment que les comparaisons sur une colonne ou une table particulière soient sensibles à la casse, vous devez modifier la colonne ou la table pour qu’elle utilise le tri <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_bin</span></code>. Dans ce cas, la chose importante à savoir est que si vous utilisez MySQLdb 1.2.2, la base de données dans Django renvoie alors des chaînes d’octets (au lieu de chaînes Unicode) pour tous les champs de type caractère. Il s’agit d’une grosse modification par rapport à la pratique normale dans Django de <em>toujours</em> renvoyer des chaînes Unicode. C’est donc à vous, le développeur, de gérer le fait que vous recevrez des chaînes d’octets si vous configurez des tables pour utiliser la méthode de tri <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_bin</span></code>. Django lui-même devrait généralement fonctionner correctement avec ces colonnes (sauf pour les tables <code class=\"docutils literal notranslate\"><span class=\"pre\">contrib.sessions</span></code> <code class=\"docutils literal notranslate\"><span class=\"pre\">Session</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">contrib.admin</span></code> <code class=\"docutils literal notranslate\"><span class=\"pre\">LogEntry</span></code> décrites ci-dessous), mais votre code doit parfois ajouter un appel à <code class=\"docutils literal notranslate\"><span class=\"pre\">django.utils.encoding.smart_text()</span></code> si vous voulez vraiment travailler avec des données cohérentes – Django ne le fera pas pour vous (la couche principale de base de données et la couche des modèles sont séparées en interne de sorte que la couche de la base de données ne sait pas qu’il est nécessaire de faire cette conversion dans ce seul cas particulier).</p>\n<p>Si vous utilisez MySQLdb 1.2.1p2, la classe standard <a class=\"reference internal\" href=\"/fr/1.9/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> de Django renvoie des chaînes Unicode même avec un tri <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_bin</span></code>. Toutefois, les champs <a class=\"reference internal\" href=\"/fr/1.9/ref/models/fields/#django.db.models.TextField\" title=\"django.db.models.TextField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TextField</span></code></a> sont renvoyés comme une instance d’un tableau de type <code class=\"docutils literal notranslate\"><span class=\"pre\">array.array</span></code> (du module Python <code class=\"docutils literal notranslate\"><span class=\"pre\">array</span></code> standard). Django ne peut pas faire grand chose à ce sujet, puisque, encore une fois, les informations pour savoir quelles sont les conversions nécessaires ne sont pas disponibles au moment où les données sont lues dans la base de données. Ce problème a été <a class=\"reference external\" href=\"http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1495765&amp;group_id=22307&amp;atid=374932\">résolu dans MySQLdb 1.2.2</a>, donc si vous souhaitez utiliser <a class=\"reference internal\" href=\"/fr/1.9/ref/models/fields/#django.db.models.TextField\" title=\"django.db.models.TextField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TextField</span></code></a> avec <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_bin</span></code>, la solution recommandée est de mettre à jour vers la version 1.2.2, puis de traiter les chaînes d’octets comme décrit ci-dessus (ce qui ne devrait pas être trop difficile).</p>\n<p>Si vous vous décidiez à utiliser la collation <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_bin</span></code> pour certaines de vos tables avec MySQLdb 1.2.1p2 ou 1.2.2, il faut tout de même conserver la collation <code class=\"docutils literal notranslate\"><span class=\"pre\">utf8_general_ci</span></code> (par défaut) pour la table <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions.models.Session</span></code> (nommée habituellement <code class=\"docutils literal notranslate\"><span class=\"pre\">django_session</span></code>) ainsi que pour la table <a class=\"reference internal\" href=\"/fr/1.9/ref/contrib/admin/#django.contrib.admin.models.LogEntry\" title=\"django.contrib.admin.models.LogEntry\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.admin.models.LogEntry</span></code></a> (nommée habituellement <code class=\"docutils literal notranslate\"><span class=\"pre\">django_admin_log</span></code>). Ce sont les deux tables standards utilisant en interne un champ <a class=\"reference internal\" href=\"/fr/1.9/ref/models/fields/#django.db.models.TextField\" title=\"django.db.models.TextField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TextField</span></code></a>.</p>\n<p>Notez que selon les <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/5.7/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/1.9/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/1.9/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/1.9/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/1.9/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/1.9/ref/settings/#std-setting-PASSWORD\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD</span></code></a>,\n<a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a>, <a class=\"reference internal\" href=\"/fr/1.9/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/1.9/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/1.9/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/5.6/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 options de connexion MySQLdb 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>. Consultez la <a class=\"reference external\" href=\"http://mysql-python.sourceforge.net/\">documentation MySQLdb</a> pour plus de détails.</p>\n<section id=\"setting-sql-mode\">\n<span id=\"mysql-sql-mode\"></span><h4>Setting <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>From MySQL 5.7 onwards and on fresh installs of MySQL 5.6, the default value of\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code> option contains <code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_TRANS_TABLES</span></code>. That option escalates\nwarnings into errors when data are truncated upon insertion, so Django highly\nrecommends activating a <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-strict\">strict mode</a> for MySQL to prevent data loss (either\n<code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_TRANS_TABLES</span></code> or <code class=\"docutils literal notranslate\"><span class=\"pre\">STRICT_ALL_TABLES</span></code>).</p>\n<p>If you need to customize the SQL mode, you can set the <code class=\"docutils literal notranslate\"><span class=\"pre\">sql_mode</span></code> variable\nlike other MySQL options: either in a config file or with the entry\n<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> in the\n<a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-OPTIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code></a> part of your database configuration in <a class=\"reference internal\" href=\"/fr/1.9/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>\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/1.9/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/1.9/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/1.9/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/1.9/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>, <a class=\"reference internal\" href=\"/fr/1.9/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> et <a class=\"reference internal\" href=\"/fr/1.9/ref/models/fields/#django.db.models.CommaSeparatedIntegerField\" title=\"django.db.models.CommaSeparatedIntegerField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CommaSeparatedIntegerField</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. De plus, les versions de MySQLdb plus anciennes que 1.2.5 contiennent <a class=\"reference external\" href=\"https://github.com/farcepest/MySQLdb1/issues/24\">une anomalie</a> qui empêche également l’utilisation des fractions de secondes avec MySQL.</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/1.9/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/1.9/topics/migrations/#data-migrations\"><span class=\"std std-ref\">migration de données</span></a>.</p>\n<aside class=\"version-note version-changed\" data-version=\"1.8\">\n<p class=\"version-note-title\">Changed in Django 1.8</p><p>Précédemment, Django tronquait les fractions de secondes des valeurs <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">time</span></code> avec le moteur MySQL. Il laisse maintenant la base de données décider si elle veut tenir compte de cette partie de la valeur ou non. Par défaut, les nouvelles colonnes <code class=\"docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">TimeField</span></code> sont dorénavant créées avec la prise en charge des fractions de secondes sur MySQL 5.6.4 ou plus récent et les moteurs <code class=\"docutils literal notranslate\"><span class=\"pre\">mysqlclient</span></code> ou MySQLdb 1.2.5 ou plus récent.</p>\n</aside>\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/1.9/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/1.9/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/1.9/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 ne gère pas l’option <code class=\"docutils literal notranslate\"><span class=\"pre\">NOWAIT</span></code> 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 <code class=\"docutils literal notranslate\"><span class=\"pre\">nowait=True</span></code>, une exception de type <code class=\"docutils literal notranslate\"><span class=\"pre\">DatabaseError</span></code> sera générée.</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/1.9/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/1.9/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/1.9/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/1.9/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/1.9/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=\"id11\"></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><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/1.9/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/1.9/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/1.9/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/1.9/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=\"old-sqlite-and-case-expressions\">\n<h3>Expressions <code class=\"docutils literal notranslate\"><span class=\"pre\">CASE</span></code> et anciennes versions de SQLite<a class=\"heading-anchor\" href=\"#old-sqlite-and-case-expressions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>SQLite 3.6.23.1 et ses versions précédentes contiennent une anomalie lors du <a class=\"reference external\" href=\"https://code.djangoproject.com/ticket/24148\">traitement des paramètres de requête</a> dans une expression <code class=\"docutils literal notranslate\"><span class=\"pre\">CASE</span></code> contenant une clause <code class=\"docutils literal notranslate\"><span class=\"pre\">ELSE</span></code> et de l’arithmétique.</p>\n<p>SQLite 3.6.23.1 a été publiée en mars 2010 et la plupart des distributions binaires actuelles sur diverses plates-formes contiennent une version plus récente de SQLite, à l’exception notable des installeurs Python 2.7 pour Windows.</p>\n<p>Au moment d’écrire ces lignes, la dernière version pour Windows, Python 2.7.10, inclut SQLite 3.6.21. Vous pouvez installer <code class=\"docutils literal notranslate\"><span class=\"pre\">pysqlite2</span></code> ou remplacer <code class=\"docutils literal notranslate\"><span class=\"pre\">sqlite3.dll</span></code> (installé par défaut dans <code class=\"docutils literal notranslate\"><span class=\"pre\">C:\\Python27\\DLLs</span></code>) par une version plus récente provenant de <a class=\"reference external\" href=\"https://www.sqlite.org/\">https://www.sqlite.org/</a> afin de remédier à ce problème.</p>\n</section>\n<section id=\"using-newer-versions-of-the-sqlite-db-api-2-0-driver\">\n<span id=\"using-newer-versions-of-pysqlite\"></span><h3>Utilisation de versions plus récentes du pilote SQLite DB-API 2.0<a class=\"heading-anchor\" href=\"#using-newer-versions-of-the-sqlite-db-api-2-0-driver\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django utilise de préférence le module <code class=\"docutils literal notranslate\"><span class=\"pre\">pysqlite2</span></code> au lieu du module <code class=\"docutils literal notranslate\"><span class=\"pre\">sqlite3</span></code> livré avec la bibliothèque Python standard, s’il le trouve installé.</p>\n<p>Cela donne la possibilité de mettre à niveau à la fois l’interface DB-API 2.0 ou SQLite 3 elle-même à des versions plus récentes que celles incluses dans votre distribution Python binaire, si le besoin s’en fait sentir.</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 ne fera que prolonger un peu le temps d’attente de SQLite avant de produire des erreurs « database is locked » ; 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>\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 supports <a class=\"reference external\" href=\"http://www.oracle.com/\">Oracle Database Server</a> versions 11.2 and higher. Versions\n4.3.1 through 5.2.1 of the <a class=\"reference external\" href=\"http://cx-oracle.sourceforge.net/\">cx_Oracle</a> Python driver are supported, although\n5.1.3 or later is recommended as these versions support Python 3.</p>\n<p>Notez qu’en raison d’un bogue de corruption Unicode dans <code class=\"docutils literal notranslate\"><span class=\"pre\">cx_Oracle</span></code> 5.0, cette version du pilote ne doit <strong>pas</strong> être utilisée avec Django ; <code class=\"docutils literal notranslate\"><span class=\"pre\">cx_Oracle</span></code> 5.0.1 résout ce problème, donc si vous avez besoin d’une version plus récente, utilisez au moins la version 5.0.1.</p>\n<p>La version <code class=\"docutils literal notranslate\"><span class=\"pre\">cx_Oracle</span></code> 5.0.1 ou ultérieure peut être compilée de manière facultative avec la variable d’environnement <code class=\"docutils literal notranslate\"><span class=\"pre\">WITH_UNICODE</span></code>. C’est recommandé, mais pas obligatoire.</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>Notez que même si le rôle RESOURCE possède les privilèges requis CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE et CREATE TRIGGER et qu’un utilisateur disposant de RESOURCE WITH ADMIN OPTION peut accorder le privilège RESOURCE, cet utilisateur ne peut pas accorder de privilèges individuels (par ex. CREATE TABLE), ce qui fait que  RESOURCE WITH ADMIN OPTION n’est généralement pas suffisant pour exécuter les tests.</p>\n<p>Certaines suites de tests créent aussi des vues ; pour exécuter celles-ci, l’utilisateur a aussi besoin du privilège CREATE VIEW WITH ADMIN OPTION. C’est nécessaire en particulier pour la propre suite de tests de Django.</p>\n<aside class=\"version-note version-changed\" data-version=\"1.8\">\n<p class=\"version-note-title\">Changed in Django 1.8</p><p>Avant Django 1.8, l’utilisateur de test recevait les rôles CONNECT et RESOURCE, ce qui fait que les privilèges supplémentaires requis pour exécuter la suite de tests étaient différents.</p>\n</aside>\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/1.9/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/1.9/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/1.9/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/1.9/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/1.9/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/1.9/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>\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<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 (“”) plutôt que NULL, 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=\"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://github.com/sqlanywhere/sqlany-django\">SAP SQL Anywhere</a></p></li>\n<li><p><a class=\"reference external\" href=\"https://pypi.python.org/pypi/ibm_db/\">IBM DB2</a></p></li>\n<li><p><a class=\"reference external\" href=\"https://django-mssql.readthedocs.io/en/latest/\">Microsoft SQL Server</a></p></li>\n<li><p><a class=\"reference external\" href=\"https://github.com/maxirobaina/django-firebird\">Firebird</a></p></li>\n<li><p><a class=\"reference external\" href=\"https://github.com/lionheart/django-pyodbc/\">ODBC</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":"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 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":"MySQLdb","anchor":"id8","children":[]},{"title":"mysqlclient","anchor":"id9","children":[]},{"title":"MySQL Connector/Python","anchor":"id10","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":"Setting sql_mode","anchor":"setting-sql-mode","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":"Expressions CASE et anciennes versions de SQLite","anchor":"old-sqlite-and-case-expressions","children":[]},{"title":"Utilisation de versions plus récentes du pilote SQLite DB-API 2.0","anchor":"using-newer-versions-of-the-sqlite-db-api-2-0-driver","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":"Notes sur Oracle","anchor":"oracle-notes","children":[{"title":"Connexion à la base de données","anchor":"id13","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":"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/1.9/ref/"}],"prev":{"docname":"ref/csrf","title":"Protection contre le « Cross site request forgery » (CSRF)","url":"/fr/1.9/ref/csrf/"},"next":{"docname":"ref/django-admin","title":"django-admin et manage.py","url":"/fr/1.9/ref/django-admin/"},"formats":{"html":"/fr/1.9/ref/databases/","markdown":"/fr/1.9/ref/databases.md","json":"/fr/1.9/ref/databases.json"},"source":"https://github.com/django/django/blob/stable/1.9.x/docs/ref/databases.txt","official":"https://docs.djangoproject.com/fr/1.9/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","fr","ja","id","pt-br","es"]}