{"title":"Écriture de champs de modèles personnalisés","version":"3.2","locale":"fr","docname":"howto/custom-model-fields","url":"/fr/3.2/howto/custom-model-fields/","canonical":"https://djangodocs.dev/fr/3.2/howto/custom-model-fields/","summary":"Introduction Lien vers cette rubrique # La documentation de référence sur les modèles explique comment utiliser les classes de champs standard de Django : CharField…","html":"<h1>Écriture de champs de modèles personnalisés<a class=\"heading-anchor\" href=\"#writing-custom-model-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<section id=\"introduction\">\n<h2>Introduction<a class=\"heading-anchor\" href=\"#introduction\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>La documentation de <a class=\"reference internal\" href=\"/fr/3.2/topics/db/models/\"><span class=\"doc\">référence sur les modèles</span></a> explique comment utiliser les classes de champs standard de Django : <a class=\"reference internal\" href=\"/fr/3.2/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/3.2/ref/models/fields/#django.db.models.DateField\" title=\"django.db.models.DateField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateField</span></code></a>, etc. Dans la plupart des cas, ces classes sont suffisantes. Cependant, il peut arriver que l’offre de Django ne réponde pas à toutes vos exigences, ou que vous vouliez utiliser un champ totalement différent de ceux mis à disposition par Django.</p>\n<p>Les types de champs intégrés de Django ne gèrent pas tous les types possibles de colonnes de bases de données, mais seulement les plus courants comme <code class=\"docutils literal notranslate\"><span class=\"pre\">VARCHAR</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">INTEGER</span></code>. Pour des types de colonnes moins usités, comme les polygones géographiques ou même des types définis par les utilisateurs du style des <a class=\"reference external\" href=\"https://www.postgresql.org/docs/current/sql-createtype.html\">types PostgreSQL personnalisés</a>, vous pouvez définir vos propres sous-classes de <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code>.</p>\n<p>D’un autre côté, vous pourriez avoir un objet Python complexe pouvant être sérialisé d’une manière ou d’une autre dans un type de colonne standard d’une base de données. C’est une autre situation où une sous-classe de  <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> peut vous aider à utiliser cet objet avec vos modèles.</p>\n<section id=\"our-example-object\">\n<h3>Notre exemple d’objet<a class=\"heading-anchor\" href=\"#our-example-object\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>La création de champs personnalisés exige un peu d’attention aux détails. Pour rendre les choses plus faciles à suivre, nous allons utiliser un même exemple tout au long de ce document : encapsuler un objet Python représentant une distribution de cartes dans une main de <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Contract_bridge\">Bridge</a>. Ne vous inquiétez pas, il n’y a pas besoin de savoir jouer au Bridge pour suivre cet exemple. Il suffit de savoir que les 52 cartes sont distribuées équitablement entre quatre joueurs, traditionnellement appelés <em>nord</em>, <em>est</em>, <em>sud</em> et <em>ouest</em>. Notre classe ressemble à 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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Hand</span><span class=\"p\">:</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;A hand of cards (bridge style)&quot;&quot;&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">north</span><span class=\"p\">,</span> <span class=\"n\">east</span><span class=\"p\">,</span> <span class=\"n\">south</span><span class=\"p\">,</span> <span class=\"n\">west</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Input parameters are lists of cards (&#39;Ah&#39;, &#39;9s&#39;, etc.)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">north</span> <span class=\"o\">=</span> <span class=\"n\">north</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">east</span> <span class=\"o\">=</span> <span class=\"n\">east</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">south</span> <span class=\"o\">=</span> <span class=\"n\">south</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">west</span> <span class=\"o\">=</span> <span class=\"n\">west</span>\n\n    <span class=\"c1\"># ... (other possibly useful methods omitted) ...</span>\n</code></pre></div>\n<p>C’est une classe Python ordinaire sans spécificité Django. Nous aimerions pouvoir faire des choses telles que celles-ci dans nos modèles (en supposant que l’attribut <code class=\"docutils literal notranslate\"><span class=\"pre\">hand</span></code> du modèle est une instance de <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</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\">example</span> <span class=\"o\">=</span> <span class=\"n\">MyModel</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">example</span><span class=\"o\">.</span><span class=\"n\">hand</span><span class=\"o\">.</span><span class=\"n\">north</span><span class=\"p\">)</span>\n\n<span class=\"n\">new_hand</span> <span class=\"o\">=</span> <span class=\"n\">Hand</span><span class=\"p\">(</span><span class=\"n\">north</span><span class=\"p\">,</span> <span class=\"n\">east</span><span class=\"p\">,</span> <span class=\"n\">south</span><span class=\"p\">,</span> <span class=\"n\">west</span><span class=\"p\">)</span>\n<span class=\"n\">example</span><span class=\"o\">.</span><span class=\"n\">hand</span> <span class=\"o\">=</span> <span class=\"n\">new_hand</span>\n<span class=\"n\">example</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Nous écrivons et lisons dans l’attribut <code class=\"docutils literal notranslate\"><span class=\"pre\">hand</span></code> de notre modèle comme on le ferait avec tout autre classe Python. L’astuce est d’indiquer à Django comment enregistrer et charger un tel objet.</p>\n<p>Pour pouvoir utiliser la classe <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code> dans nos modèles, nous ne devons <strong>en aucune façon</strong> modifier cette classe. C’est idéal, car cela signifie qu’il est facilement possible d’implémenter la fonctionnalité « modèle » pour des classes existantes dont le code source n’est pas modifiable.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Il se peut que vous vouliez uniquement profiter de types personnalisés de colonnes de bases de données et gérer les données comment des types Python standards dans vos modèles ; chaînes ou nombres à virgules, par exemple. Cette situation est semblable à notre exemple <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code> et nous signalerons d’éventuelles différences quand elles apparaîtront.</p>\n</aside>\n</section>\n</section>\n<section id=\"background-theory\">\n<h2>Contexte théorique<a class=\"heading-anchor\" href=\"#background-theory\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"database-storage\">\n<h3>Stockage de base de données<a class=\"heading-anchor\" href=\"#database-storage\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Commençons par les champs de modèles. Si on le décompose, un champ de modèle est un moyen de traiter un objet Python normal (une chaîne, une valeur booléenne, un <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code> ou un objet plus complexe comme <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code>) et de le convertir en un format adapté à l’utilisation avec une base de données (ce format convient également pour la sérialisation, mais nous verrons plus loin que cela se conçoit assez naturellement lorsque la partie base de données est maîtrisée).</p>\n<p>D’une manière ou d’une autre, les champs d’un modèle doivent être transformés pour correspondre à un type de colonne d’une base de données. Des bases de données différentes fournissent différents choix de types de colonnes valables, mais la règle est toujours la même : ce sont ces types avec lesquels vous devez travailler. Tout ce que vous voulez stocker dans la base de données doit correspondre à l’un de ces types.</p>\n<p>Normalement, soit vous écrivez un champ Django qui correspondra à un type particulier de colonne de base de données, soit il faut trouver une manière de convertir vos données, par exemple en une chaîne.</p>\n<p>Pour notre exemple <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code>, nous pourrions convertir les données des cartes en une chaîne de 104 caractères en concaténant toutes les cartes dans un ordre prédéterminé, par exemple d’abord toutes les cartes <em>nord</em>, puis toutes les cartes <em>est</em>, <em>sud</em> et <em>ouest</em>. Ainsi les objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code> peuvent être enregistrés dans des colonnes texte ou caractères de la base de données.</p>\n</section>\n<section id=\"what-does-a-field-class-do\">\n<h3>Que fait une classe de champ ?<a class=\"heading-anchor\" href=\"#what-does-a-field-class-do\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Tous les champs Django (et lorsque nous parlons de <em>champs</em> dans ce document, nous parlons toujours de champs de modèles et non pas de <a class=\"reference internal\" href=\"/fr/3.2/ref/forms/fields/\"><span class=\"doc\">champs de formulaires</span></a>) sont des sous-classes de <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.db.models.Field</span></code></a>. La plupart des informations que Django conserve sur un champ sont communs à tous les champs (nom, texte d’aide, unicité, etc.). Le stockage de toutes ces informations est géré par <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code>. Nous verrons plus précisément ce que peut faire <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> un peu plus tard ; pour l’instant, contentons-nous de savoir que tout hérite de <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> et personnalise les éléments clés du comportement de la classe.</p>\n<p>Il est important de réaliser qu’une classe de champ Django n’est pas ce qui est stocké dans les attributs de vos modèles. Les attributs des modèles contiennent des objets Python habituels. Les classes de champs que vous définissez dans un modèle sont en réalité stockés dans la classe <code class=\"docutils literal notranslate\"><span class=\"pre\">Meta</span></code> au moment de la création de la classe de modèle (il n’est pas important ici de connaître les détails précis de ce processus). Ceci est dû au fait que les classes de champs ne sont pas nécessaires tant qu’il s’agit simplement de créer et modifier des attributs. Par contre, elles fournissent les mécanismes de conversion entre les valeurs d’attributs et ce qui est effectivement stocké dans la base de données ou envoyé au <a class=\"reference internal\" href=\"/fr/3.2/topics/serialization/\"><span class=\"doc\">sérialiseur</span></a>.</p>\n<p>Gardez ceci à l’esprit lors de la création de vos propres champs personnalisés. La sous-classe <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> Django que vous écrivez fournit les mécanismes de conversion entre vos instances Python et les valeurs de base de données ou de sérialisation de diverses manières (il existe par exemple des différences entre le stockage d’une valeur et son utilisation dans une requête). Si tout cela semble un peu compliqué, ne vous inquiétez pas, cela deviendra plus clair dans les exemples ci-dessous. Rappelez-vous seulement que vous allez souvent créer deux classes lorsque vous voulez créer un champ personnalisé :</p>\n<ul class=\"simple\">\n<li><p>La première classe constitue l’objet Python que vos utilisateurs vont manipuler. Ils l’utiliseront comme attribut de modèle, ils liront ses valeurs à destination de l’affichage, et ainsi de suite. Il s’agit là de la classe <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code> de notre exemple.</p></li>\n<li><p>La seconde classe est la sous-classe de <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code>. C’est la classe qui sait comment convertir votre première classe de sa forme utile pour le stockage vers sa forme Python et vice versa.</p></li>\n</ul>\n</section>\n</section>\n<section id=\"writing-a-field-subclass\">\n<h2>Écriture d’une sous-classe de champ<a class=\"heading-anchor\" href=\"#writing-a-field-subclass\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Lors de la planification de votre sous-classe de <a class=\"reference internal\" href=\"/fr/3.2/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>, réfléchissez d’abord à quelle classe <a class=\"reference internal\" href=\"/fr/3.2/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> existante votre nouveau champ ressemble le plus. Serait-il possible d’hériter d’un champ Django existant et d’économiser un peu de travail ? Si non, vous devrez hériter de la classe <a class=\"reference internal\" href=\"/fr/3.2/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> qui est le parent de toutes les autres.</p>\n<p>L’initialisation du nouveau champ consiste à séparer tout paramètre qui est spécifique à votre champ, des paramètres standards, et de transmettre ces derniers à la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> de <a class=\"reference internal\" href=\"/fr/3.2/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> (ou d’une autre classe parente).</p>\n<p>Dans notre exemple, nous appellerons notre champ <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code> (il est conseillé d’appeler votre sous-classe de <a class=\"reference internal\" href=\"/fr/3.2/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> sur le modèle <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;QuelqueChose&gt;Field</span></code> afin qu’on distingue rapidement qu’il s’agit d’une sous-classe de <a class=\"reference internal\" href=\"/fr/3.2/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>). Notre champ ne ressemble à aucun autre champ existant, nous allons donc hériter directement de <a class=\"reference internal\" href=\"/fr/3.2/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>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">HandField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n\n    <span class=\"n\">description</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;A hand of cards (bridge style)&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s1\">&#39;max_length&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"mi\">104</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Le champ <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code> accepte la plupart des options standards de champs (voir liste ci-dessous), mais nous voulons nous assurer que sa longueur soit fixe, étant donné qu’il ne doit stocker que les valeurs de 52 cartes plus leur couleur ; 104 caractères au total.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Beaucoup de champs de modèles Django acceptent des options qui ne sont pas exploitées. Par exemple, vous pouvez passer à la fois <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.editable\" title=\"django.db.models.Field.editable\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">editable</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateField.auto_now\" title=\"django.db.models.DateField.auto_now\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">auto_now</span></code></a> à <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateField\" title=\"django.db.models.DateField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.db.models.DateField</span></code></a> et il ignorera le paramètre <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.editable\" title=\"django.db.models.Field.editable\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">editable</span></code></a> (la définition d”<a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateField.auto_now\" title=\"django.db.models.DateField.auto_now\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">auto_now</span></code></a> implique que``editable=False``). Aucune erreur ne survient dans ce cas.</p>\n<p>Ce comportement simplifie les classes de champs, car elles n’ont pas besoin de vérifier les options qui ne sont pas nécessaires. Elles transmettent toutes les options à la classe parente et ne les utilisent plus. Il ne tient qu’à vous d’être plus strict sur les options acceptées, ou d’adopter le comportement plus permissif des champs actuels.</p>\n</aside>\n<p>La méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">Field.__init__()</span></code> accepte les paramètres suivants :</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.verbose_name\" title=\"django.db.models.Field.verbose_name\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">verbose_name</span></code></a></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.primary_key\" title=\"django.db.models.Field.primary_key\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">primary_key</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.CharField.max_length\" title=\"django.db.models.CharField.max_length\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">max_length</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.unique\" title=\"django.db.models.Field.unique\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">unique</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.blank\" title=\"django.db.models.Field.blank\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">blank</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.null\" title=\"django.db.models.Field.null\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">null</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_index\" title=\"django.db.models.Field.db_index\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">db_index</span></code></a></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">rel</span></code>: utilisé pour les champs de liaison (comme <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code></a>). Uniquement pour une utilisation avancée.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.default\" title=\"django.db.models.Field.default\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">default</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.editable\" title=\"django.db.models.Field.editable\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">editable</span></code></a></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">serialize</span></code>: si <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>, le champ ne sera pas sérialisé lorsque le modèle est transmis aux <a class=\"reference internal\" href=\"/fr/3.2/topics/serialization/\"><span class=\"doc\">sérialiseurs</span></a> de Django. La valeur par défaut est <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.unique_for_date\" title=\"django.db.models.Field.unique_for_date\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">unique_for_date</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.unique_for_month\" title=\"django.db.models.Field.unique_for_month\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">unique_for_month</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.unique_for_year\" title=\"django.db.models.Field.unique_for_year\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">unique_for_year</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.choices\" title=\"django.db.models.Field.choices\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">choices</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.help_text\" title=\"django.db.models.Field.help_text\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">help_text</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_column\" title=\"django.db.models.Field.db_column\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">db_column</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_tablespace\" title=\"django.db.models.Field.db_tablespace\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">db_tablespace</span></code></a> : seulement pour la création d’index, pour autant que le moteur gère les <a class=\"reference internal\" href=\"/fr/3.2/topics/db/tablespaces/\"><span class=\"doc\">espaces de tables</span></a>. Vous pouvez généralement ignorer cette option.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.auto_created\" title=\"django.db.models.Field.auto_created\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">auto_created</span></code></a>: vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> si le champ a été créé automatiquement, comme pour le champ <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.OneToOneField\" title=\"django.db.models.OneToOneField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">OneToOneField</span></code></a> utilisé dans un contexte d’héritage de modèles. Pour utilisation avancée uniquement.</p></li>\n</ul>\n<p>Toutes les options sans explications dans la liste ci-dessus ont la même signification que pour les champs Django normaux. Consultez la  <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/\"><span class=\"doc\">documentation sur les champs</span></a> pour des exemples et des détails.</p>\n<section id=\"field-deconstruction\">\n<span id=\"custom-field-deconstruct-method\"></span><h3>Déconstruction de champ<a class=\"heading-anchor\" href=\"#field-deconstruction\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>La contrepartie à l’écriture de la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__init</span> <span class=\"pre\">__()</span></code> est l’écriture de la méthode <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.deconstruct\" title=\"django.db.models.Field.deconstruct\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">deconstruct()</span></code></a>. Celle-ci est utilisée durant les <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">:docs:`migrations de modèles &lt;/topics/migrations&gt;`</span></a> pour indiquer à Django comment prendre une instance du nouveau champ afin de le réduire en format sérialisé ; en particulier, le choix des paramètres à passer à <code class=\"docutils literal notranslate\"><span class=\"pre\">__init</span> <span class=\"pre\">__()</span></code> pour le recréer.</p>\n<p>Si vous n’avez pas ajouté d’options supplémentaires au champ dont vous avez hérité, il n’y a alors pas besoin d’écrire une nouvelle méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">deconstruct()</span></code>. Si toutefois vous modifiez les paramètres passés à <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> (comme nous l’avons fait avec <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code>), il sera nécessaire de compléter les valeurs transmises.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">deconstruct()</span></code> renvoie un tuple de quatre éléments : le nom d’attribut du champ, le chemin d’importation complet de la classe du champ, les paramètres positionnels (sous forme de liste), et les paramètres nommés (sous forme de dictionnaire). Notez la différence avec la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">deconstruct()</span></code> des <a class=\"reference internal\" href=\"/fr/3.2/topics/migrations/#custom-deconstruct-method\"><span class=\"std std-ref\">classes personnalisées</span></a> qui renvoie un tuple de trois éléments.</p>\n<p>En tant qu’auteur de champ personnalisé, vous n’avez pas besoin de vous soucier des deux premières valeurs ; la classe de base <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> contient tout le code pour déterminer le nom d’attribut et le chemin d’importation du champ. Vous devez cependant vous préoccuper des paramètres positionnels et nommés, puisque ceux-ci font généralement partie des éléments que vous modifiez.</p>\n<p>Par exemple, dans notre classe <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code>, nous forçons toujours l’utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">max_length</span></code> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code>. La méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">deconstruct()</span></code> de la classe de base <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> le verra et essayera de le renvoyer dans les paramètres nommés ; ainsi, nous pouvons le supprimer des paramètres nommés pour une meilleure lisibilité :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">HandField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s1\">&#39;max_length&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"mi\">104</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">deconstruct</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">name</span><span class=\"p\">,</span> <span class=\"n\">path</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">deconstruct</span><span class=\"p\">()</span>\n        <span class=\"k\">del</span> <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s2\">&quot;max_length&quot;</span><span class=\"p\">]</span>\n        <span class=\"k\">return</span> <span class=\"n\">name</span><span class=\"p\">,</span> <span class=\"n\">path</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span>\n</code></pre></div>\n<p>Si vous ajoutez un nouveau paramètre nommé, vous devez écrire vous-même du code dans <code class=\"docutils literal notranslate\"><span class=\"pre\">deconstruct()</span></code> qui place sa valeur dans <code class=\"docutils literal notranslate\"><span class=\"pre\">kwargs</span></code>. Vous devriez aussi omettre la valeur de <code class=\"docutils literal notranslate\"><span class=\"pre\">kwargs</span></code> lorsqu’il n’est pas nécessaire de reconstruire l’état du champ, comme par exemple lorsque la valeur par défaut est utilisée</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CommaSepField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"s2\">&quot;Implements comma-separated storage of lists&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">separator</span><span class=\"o\">=</span><span class=\"s2\">&quot;,&quot;</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">separator</span> <span class=\"o\">=</span> <span class=\"n\">separator</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">deconstruct</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">name</span><span class=\"p\">,</span> <span class=\"n\">path</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">deconstruct</span><span class=\"p\">()</span>\n        <span class=\"c1\"># Only include kwarg if it&#39;s not the default</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">separator</span> <span class=\"o\">!=</span> <span class=\"s2\">&quot;,&quot;</span><span class=\"p\">:</span>\n            <span class=\"n\">kwargs</span><span class=\"p\">[</span><span class=\"s1\">&#39;separator&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">separator</span>\n        <span class=\"k\">return</span> <span class=\"n\">name</span><span class=\"p\">,</span> <span class=\"n\">path</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span>\n</code></pre></div>\n<p>Des exemples plus complexes sont au-delà de la portée de ce document, mais rappelez-vous – pour toute configuration de votre instance de champ, <code class=\"docutils literal notranslate\"><span class=\"pre\">deconstruct()</span></code> doit renvoyer les paramètres que vous pouvez passer à <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__</span></code> afin de reconstruire cet état.</p>\n<p>Portez une attention toute particulière si vous définissez de nouvelles valeurs par défaut pour les paramètres de la classe parente <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code>; vous devez vous assurer qu’elles sont toujours incluses, sinon elles pourraient disparaître si elles prennent les anciennes valeurs par défaut.</p>\n<p>En outre, essayez d’éviter de renvoyer les valeurs en tant que paramètres positionnels ; autant que possible, renvoyez les valeurs en tant que paramètres nommés pour une compatibilité future maximale. Si vous changez plutôt le nom que la position des éléments dans la liste des paramètres du constructeur, les paramètres positionnels sont préférables, mais gardez à l’esprit que les gens reconstruiront votre champ à partir de la version sérialisée pendant un certain temps (voire des années), selon la durée de vie de vos migrations.</p>\n<p>Vous pouvez voir les résultats de la déconstruction en regardant les migrations qui incluent ledit champ, et vous pouvez tester la déconstruction dans les tests unitaires en déconstruisant et reconstruisant le champ :</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\">name</span><span class=\"p\">,</span> <span class=\"n\">path</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span> <span class=\"o\">=</span> <span class=\"n\">my_field_instance</span><span class=\"o\">.</span><span class=\"n\">deconstruct</span><span class=\"p\">()</span>\n<span class=\"n\">new_instance</span> <span class=\"o\">=</span> <span class=\"n\">MyField</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n<span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">my_field_instance</span><span class=\"o\">.</span><span class=\"n\">some_attribute</span><span class=\"p\">,</span> <span class=\"n\">new_instance</span><span class=\"o\">.</span><span class=\"n\">some_attribute</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"changing-a-custom-field-s-base-class\">\n<h3>Modification de la classe de base d’un champ personnalisé<a class=\"heading-anchor\" href=\"#changing-a-custom-field-s-base-class\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il n’est pas possible de modifier la classe de base d’un champ personnalisé, car Django ne détectera pas le changement et ne créera pas de migration. Par exemple, si vous commencez avec :</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\">CustomCharField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>puis que vous décidez de vous baser plutôt sur <code class=\"docutils literal notranslate\"><span class=\"pre\">TextField</span></code>, vous ne pouvez pas simplement modifier la sous-classe 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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CustomCharField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">TextField</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Vous devez plutôt créer une nouvelle classe de champ personnalisé et mettre à jour vos modèles pour référencer cette nouvelle classe :</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\">CustomCharField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CustomTextField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">TextField</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Comme discuté dans <a class=\"reference internal\" href=\"/fr/3.2/topics/migrations/#migrations-removing-model-fields\"><span class=\"std std-ref\">suppression de champs</span></a>, vous devez conserver la classe <code class=\"docutils literal notranslate\"><span class=\"pre\">CustomCharField</span></code> originale tant que vous conservez des migrations qui la référencent.</p>\n</section>\n<section id=\"documenting-your-custom-field\">\n<h3>Documentation du champ personnalisé<a class=\"heading-anchor\" href=\"#documenting-your-custom-field\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme toujours, il est souhaitable de documenter votre type de champ, afin que les utilisateurs sachent de quoi il s’agit. En plus de lui fournir une chaîne « docstring » utile pour les développeurs, vous pouvez également permettre aux utilisateurs de l’application d’administration de voir une courte description du type de champ via l’application <a class=\"reference internal\" href=\"/fr/3.2/ref/contrib/admin/admindocs/\"><span class=\"doc\">django.contrib.admindocs</span></a>. Pour ce faire, fournissez un texte descriptif dans l’attribut de classe <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.description\" title=\"django.db.models.Field.description\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">description</span></code></a> du champ personnalisé. Dans l’exemple ci-dessus, la description affichée par l’application <code class=\"docutils literal notranslate\"><span class=\"pre\">admindocs</span></code> pour un <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code> sera « A hand of cards (bridge style) ».</p>\n<p>Dans l’affichage <a class=\"reference internal\" href=\"/fr/3.2/ref/contrib/admin/admindocs/#module-django.contrib.admindocs\" title=\"django.contrib.admindocs: Django's admin documentation generator.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.admindocs</span></code></a>, la description du champ est interpolée avec <code class=\"docutils literal notranslate\"><span class=\"pre\">field.__dict__</span></code>, ce qui permet à la description de contenir des paramètres du champ. Par exemple, la description de <a class=\"reference internal\" href=\"/fr/3.2/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> est :</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\">description</span> <span class=\"o\">=</span> <span class=\"n\">_</span><span class=\"p\">(</span><span class=\"s2\">&quot;String (up to </span><span class=\"si\">%(max_length)s</span><span class=\"s2\">)&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"useful-methods\">\n<h3>Méthodes utiles<a class=\"heading-anchor\" href=\"#useful-methods\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Après avoir créé la sous-classe de <a class=\"reference internal\" href=\"/fr/3.2/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>, il peut être utile de surcharger quelques méthodes standards, en fonction du comportement du champ. La liste de méthodes ci-dessous est plus ou moins dans l’ordre décroissant d’importance, il faut donc commencer par les premières.</p>\n<section id=\"custom-database-types\">\n<span id=\"id1\"></span><h4>Types de base de données personnalisés<a class=\"heading-anchor\" href=\"#custom-database-types\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Disons que vous avez créé un type personnalisé PostgreSQL appelé <code class=\"docutils literal notranslate\"><span class=\"pre\">mytype</span></code>. Vous pouvez dériver <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> et implémenter la méthode <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_type\" title=\"django.db.models.Field.db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">db_type()</span></code></a>, comme suit :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MytypeField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_type</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;mytype&#39;</span>\n</code></pre></div>\n<p>Après avoir créé <code class=\"docutils literal notranslate\"><span class=\"pre\">MytypeField</span></code>, il est possible de l’utiliser dans n’importe quel modèle, comme pour tout autre type <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Person</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=\"n\">name</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">80</span><span class=\"p\">)</span>\n    <span class=\"n\">something_else</span> <span class=\"o\">=</span> <span class=\"n\">MytypeField</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Si votre objectif est de créer une application indépendante du choix de la base de données, vous devriez tenir compte des différences de types de colonne de base de données. Par exemple, le type de colonne date/heure dans PostgreSQL est appelé <code class=\"docutils literal notranslate\"><span class=\"pre\">timestamp</span></code> alors que la même colonne dans MySQL est appelée <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code>. Vous pouvez gérer cela dans une méthode <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_type\" title=\"django.db.models.Field.db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">db_type()</span></code></a> en vous basant sur l’attribut <code class=\"docutils literal notranslate\"><span class=\"pre\">connection.vendor</span></code>. Les noms actuels des fournisseurs intégrés sont : <code class=\"docutils literal notranslate\"><span class=\"pre\">sqlite</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">postgresql</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">mysql</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">oracle</span></code>.</p>\n<p>Par exemple :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyDateField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_type</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">vendor</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;mysql&#39;</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"s1\">&#39;datetime&#39;</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"s1\">&#39;timestamp&#39;</span>\n</code></pre></div>\n<p>Les méthodes <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_type\" title=\"django.db.models.Field.db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">db_type()</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.rel_db_type\" title=\"django.db.models.Field.rel_db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">rel_db_type()</span></code></a> sont appelées par Django lorsque le système construit les instructions <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TABLE</span></code> pour votre application – c’est-à-dire lors de la création initiale des tables. Elles sont aussi appelées lors de la construction d’une clause <code class=\"docutils literal notranslate\"><span class=\"pre\">WHERE</span></code> qui comprend le champ de modèle – c’est-à-dire lorsque vous récupérez des données à l’aide de méthodes de QuerySet telles que <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">filter()</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">exclude()</span></code> et que le champ de modèle se trouve en paramètre. Elles ne sont appelées à aucun autre moment, elles peuvent donc se permettre d’exécuter du code un peu complexe, comme la vérification de <code class=\"docutils literal notranslate\"><span class=\"pre\">connection.settings_dict</span></code> dans l’exemple ci-dessus.</p>\n<p>Certains types de colonnes de base de données acceptent des paramètres tels que <code class=\"docutils literal notranslate\"><span class=\"pre\">CHAR(25)</span></code>, où le paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">25</span></code> représente la taille maximale de la colonne. Dans de tels cas, il est plus souple de définir le paramètre dans le modèle plutôt qu’il soit codé en dur dans la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">db_type()</span></code>. Par exemple, ce ne serait pas très raisonnable d’avoir un type <code class=\"docutils literal notranslate\"><span class=\"pre\">CharMaxlength25Field</span></code> tel que ci-dessous :</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\"># This is a silly example of hard-coded parameters.</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CharMaxlength25Field</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_type</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;char(25)&#39;</span>\n\n<span class=\"c1\"># In the model:</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyModel</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=\"c1\"># ...</span>\n    <span class=\"n\">my_field</span> <span class=\"o\">=</span> <span class=\"n\">CharMaxlength25Field</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>La meilleure manière de résoudre ce problème serait d’autoriser le paramètre à être défini au moment de l’exécution, c’est-à-dire quand la classe est instanciée. Pour faire cela, implémentez la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">Field.__init__()</span></code> 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=\"c1\"># This is a much more flexible example.</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">BetterCharField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">max_length</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">max_length</span> <span class=\"o\">=</span> <span class=\"n\">max_length</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_type</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;char(</span><span class=\"si\">%s</span><span class=\"s1\">)&#39;</span> <span class=\"o\">%</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">max_length</span>\n\n<span class=\"c1\"># In the model:</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyModel</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=\"c1\"># ...</span>\n    <span class=\"n\">my_field</span> <span class=\"o\">=</span> <span class=\"n\">BetterCharField</span><span class=\"p\">(</span><span class=\"mi\">25</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Pour terminer, si votre colonne exige une configuration SQL vraiment complexe, renvoyez <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> depuis <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_type\" title=\"django.db.models.Field.db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">db_type()</span></code></a>. Cela aura pour conséquence que le code de création SQL de Django va omettre ce champ. Vous êtes alors responsable de créer la colonne dans la bonne table d’une autre manière, mais au moins cela vous permet d’indiquer à Django de ne pas intervenir dans ce processus.</p>\n<p>La méthode <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.rel_db_type\" title=\"django.db.models.Field.rel_db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">rel_db_type()</span></code></a> est appelée par des champs tels que <code class=\"docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">OneToOneField</span></code> qui pointent vers un autre champ pour déterminer leur type de colonne de base de données. Par exemple, si vous avez un <code class=\"docutils literal notranslate\"><span class=\"pre\">UnsignedAutoField</span></code>, vous avez aussi besoin que les clés étrangères qui pointent vers ce champ utilisent le même type de données :</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\"># MySQL unsigned integer (range 0 to 4294967295).</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">UnsignedAutoField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">AutoField</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_type</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;integer UNSIGNED AUTO_INCREMENT&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">rel_db_type</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;integer UNSIGNED&#39;</span>\n</code></pre></div>\n</section>\n<section id=\"converting-values-to-python-objects\">\n<span id=\"id2\"></span><h4>Conversion de valeurs en objets Python<a class=\"heading-anchor\" href=\"#converting-values-to-python-objects\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Si votre classe <a class=\"reference internal\" href=\"/fr/3.2/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> personnalisée manipule des structures de données plus complexes que des chaînes, des dates, des entiers ou des nombres à virgule, il peut être nécessaire de surcharger <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.from_db_value\" title=\"django.db.models.Field.from_db_value\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">from_db_value()</span></code></a> et <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.to_python\" title=\"django.db.models.Field.to_python\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">to_python()</span></code></a>.</p>\n<p>Si elle est présente dans la sous-classe de champ, <code class=\"docutils literal notranslate\"><span class=\"pre\">from_db_value()</span></code> sera appelée dans tous les cas où des données sont chargées à partir de la base de données, y compris dans les appels d’agrégation et les appels <a class=\"reference internal\" href=\"/fr/3.2/ref/models/querysets/#django.db.models.query.QuerySet.values\" title=\"django.db.models.query.QuerySet.values\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">values()</span></code></a>.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">to_python()</span></code> est appelée par la désérialisation et dans le cadre de la méthode  <a class=\"reference internal\" href=\"/fr/3.2/ref/models/instances/#django.db.models.Model.clean\" title=\"django.db.models.Model.clean\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">clean()</span></code></a> utilisée depuis les formulaires.</p>\n<p>En règle générale, <code class=\"docutils literal notranslate\"><span class=\"pre\">to_python()</span></code> devrait gérer de manière élégante tous les paramètres suivants :</p>\n<ul class=\"simple\">\n<li><p>Une instance ayant le type correct (par exemple <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code> dans le cas modèle de ce document).</p></li>\n<li><p>Une chaîne</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> (si le champ autorise <code class=\"docutils literal notranslate\"><span class=\"pre\">null=True</span></code>)</p></li>\n</ul>\n<p>Dans notre classe <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code>, nous stockons les données avec un champ VARCHAR dans la base de données, il faut donc pouvoir gérer des chaînes de caractères et la valeur <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">from_db_value()</span></code>. Dans``to_python()``, il est aussi nécessaire de gérer les instances de <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</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=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">re</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.exceptions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ValidationError</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils.translation</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">gettext_lazy</span> <span class=\"k\">as</span> <span class=\"n\">_</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">parse_hand</span><span class=\"p\">(</span><span class=\"n\">hand_string</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;Takes a string of cards and splits into a full hand.&quot;&quot;&quot;</span>\n    <span class=\"n\">p1</span> <span class=\"o\">=</span> <span class=\"n\">re</span><span class=\"o\">.</span><span class=\"n\">compile</span><span class=\"p\">(</span><span class=\"s1\">&#39;.</span><span class=\"si\">{26}</span><span class=\"s1\">&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">p2</span> <span class=\"o\">=</span> <span class=\"n\">re</span><span class=\"o\">.</span><span class=\"n\">compile</span><span class=\"p\">(</span><span class=\"s1\">&#39;..&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">args</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">p2</span><span class=\"o\">.</span><span class=\"n\">findall</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"n\">p1</span><span class=\"o\">.</span><span class=\"n\">findall</span><span class=\"p\">(</span><span class=\"n\">hand_string</span><span class=\"p\">)]</span>\n    <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">args</span><span class=\"p\">)</span> <span class=\"o\">!=</span> <span class=\"mi\">4</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> <span class=\"n\">ValidationError</span><span class=\"p\">(</span><span class=\"n\">_</span><span class=\"p\">(</span><span class=\"s2\">&quot;Invalid input for a Hand instance&quot;</span><span class=\"p\">))</span>\n    <span class=\"k\">return</span> <span class=\"n\">Hand</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">)</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">HandField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">from_db_value</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">expression</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"n\">value</span> <span class=\"ow\">is</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">value</span>\n        <span class=\"k\">return</span> <span class=\"n\">parse_hand</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">to_python</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">Hand</span><span class=\"p\">):</span>\n            <span class=\"k\">return</span> <span class=\"n\">value</span>\n\n        <span class=\"k\">if</span> <span class=\"n\">value</span> <span class=\"ow\">is</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">value</span>\n\n        <span class=\"k\">return</span> <span class=\"n\">parse_hand</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Remarquez que ces méthodes renvoient toujours une instance <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code>. C’est le type d’objet Python que nous voulons stocker dans l’attribut du modèle.</p>\n<p>Pour <code class=\"docutils literal notranslate\"><span class=\"pre\">to_python()</span></code>, si quoi que ce soit se passe mal durant la conversion de la valeur, il faut lever une exception de type <a class=\"reference internal\" href=\"/fr/3.2/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code></a>.</p>\n</section>\n<section id=\"converting-python-objects-to-query-values\">\n<span id=\"id3\"></span><h4>Conversion d’objets Python en valeurs de requête<a class=\"heading-anchor\" href=\"#converting-python-objects-to-query-values\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Comme l’utilisation d’une base de données nécessite une conversion dans les deux sens, si vous surchargez <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.from_db_value\" title=\"django.db.models.Field.from_db_value\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">from_db_value()</span></code></a> vous devrez aussi surcharger <a class=\"reference internal\" href=\"/fr/3.2/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> pour convertir les objets Python vers des valeurs de requête.</p>\n<p>Par exemple :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">HandField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_prep_value</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">([</span><span class=\"s1\">&#39;&#39;</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">(</span><span class=\"n\">l</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">l</span> <span class=\"ow\">in</span> <span class=\"p\">(</span><span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">north</span><span class=\"p\">,</span>\n                <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">east</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">south</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"o\">.</span><span class=\"n\">west</span><span class=\"p\">)])</span>\n</code></pre></div>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Si votre champ personnalisé utilise les types <code class=\"docutils literal notranslate\"><span class=\"pre\">CHAR</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">VARCHAR</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">TEXT</span></code> de MySQL, vous devez garantir que la méthode <a class=\"reference internal\" href=\"/fr/3.2/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> renvoie toujours un type chaîne. MySQL effectue des correspondances souples mais imprévisibles lorsque des requêtes sur ces types se font avec un nombre entier, ce qui peut faire que les résultats contiendront des objets non prévus. Ce problème ne peut pas se produire si vous renvoyez systématiquement des chaînes dans <a class=\"reference internal\" href=\"/fr/3.2/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>.</p>\n</aside>\n</section>\n<section id=\"converting-query-values-to-database-values\">\n<span id=\"id4\"></span><h4>Conversion de valeurs de requête en valeurs de base de données<a class=\"heading-anchor\" href=\"#converting-query-values-to-database-values\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Certains types de données (par exemple les dates) doivent être dans un format spécifique avant de pouvoir être utilisées par un moteur de base de données. <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.get_db_prep_value\" title=\"django.db.models.Field.get_db_prep_value\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_db_prep_value()</span></code></a> est la méthode où ces conversions doivent être réalisées. La connexion spécifique qui sera utilisée pour la requête est transmise en tant que paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">connection</span></code>. Cela vous permet d’utiliser la logique de conversion spécifique au moteur si cela est nécessaire.</p>\n<p>Par exemple, Django utilise la méthode suivante pour son champ <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.BinaryField\" title=\"django.db.models.BinaryField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">BinaryField</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_db_prep_value</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"n\">prepared</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">):</span>\n    <span class=\"n\">value</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_db_prep_value</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"n\">prepared</span><span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"n\">value</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> <span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">Database</span><span class=\"o\">.</span><span class=\"n\">Binary</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">value</span>\n</code></pre></div>\n<p>Dans le cas où votre champ personnalisé a besoin d’une conversion spéciale lors de son enregistrement qui n’est pas la même que la conversion utilisée pour les paramètres normaux dans une requête, vous pouvez surcharger <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.get_db_prep_save\" title=\"django.db.models.Field.get_db_prep_save\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_db_prep_save()</span></code></a>.</p>\n</section>\n<section id=\"preprocessing-values-before-saving\">\n<span id=\"id5\"></span><h4>Pré-traitement des valeurs avant enregistrement<a class=\"heading-anchor\" href=\"#preprocessing-values-before-saving\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Si vous souhaitez pré-traiter la valeur juste avant l’enregistrement, vous pouvez utiliser <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.pre_save\" title=\"django.db.models.Field.pre_save\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">pre_save()</span></code></a>. Par exemple, le champ <a class=\"reference internal\" href=\"/fr/3.2/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> de Django utilise cette méthode pour définir correctement l’attribut dans le cas de <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateField.auto_now\" title=\"django.db.models.DateField.auto_now\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">auto_now</span></code></a> ou <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateField.auto_now_add\" title=\"django.db.models.DateField.auto_now_add\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">auto_now_add</span></code></a>.</p>\n<p>Si vous surchargez cette méthode, vous devez renvoyez la valeur de l’attribut à la fin. Vous devriez aussi mettre à jour l’attribut du modèle si vous modifiez la valeur, afin que tout code ayant des références sur le modèle voie toujours la valeur correcte.</p>\n</section>\n<section id=\"specifying-the-form-field-for-a-model-field\">\n<span id=\"specifying-form-field-for-model-field\"></span><h4>Sélection du champ de formulaire pour un champ de modèle<a class=\"heading-anchor\" href=\"#specifying-the-form-field-for-a-model-field\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Pour personnaliser le champ de formulaire utilisé par <a class=\"reference internal\" href=\"/fr/3.2/topics/forms/modelforms/#django.forms.ModelForm\" title=\"django.forms.ModelForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ModelForm</span></code></a>, vous pouvez surcharger <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.formfield\" title=\"django.db.models.Field.formfield\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">formfield()</span></code></a>.</p>\n<p>La classe de champ de formulaire peut être indiquée via les paramètres <code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">choices_form_class</span></code> ; ce dernier est utilisé si le champ contient une liste de choix, sinon c’est <code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> qui est pris en compte. Si ces paramètres ne sont pas présents, c’est <a class=\"reference internal\" href=\"/fr/3.2/ref/forms/fields/#django.forms.CharField\" title=\"django.forms.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a> ou <a class=\"reference internal\" href=\"/fr/3.2/ref/forms/fields/#django.forms.TypedChoiceField\" title=\"django.forms.TypedChoiceField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TypedChoiceField</span></code></a> qui seront utilisés.</p>\n<p>Tout le contenu du dictionnaire <code class=\"docutils literal notranslate\"><span class=\"pre\">kwargs</span></code> est directement transmis à la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> du champ de formulaire. En principe, tout ce qu’il y a à faire est de définir une bonne valeur par défaut du paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> (ou <code class=\"docutils literal notranslate\"><span class=\"pre\">choices_form_class</span></code>) puis de déléguer le reste à la classe parente. Il est possible que vous deviez écrire un champ de formulaire personnalisé (et même un composant de formulaire). Consultez la <a class=\"reference internal\" href=\"/fr/3.2/topics/forms/\"><span class=\"doc\">documentation sur les formulaires</span></a> pour plus de détails sur ce sujet.</p>\n<p>Poursuivant notre exemple en cours, on peut écrire la méthode <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.formfield\" title=\"django.db.models.Field.formfield\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">formfield()</span></code></a> ainsi :</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\">HandField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">formfield</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"c1\"># This is a fairly standard way to set up some defaults</span>\n        <span class=\"c1\"># while letting the caller override them.</span>\n        <span class=\"n\">defaults</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">&#39;form_class&#39;</span><span class=\"p\">:</span> <span class=\"n\">MyFormField</span><span class=\"p\">}</span>\n        <span class=\"n\">defaults</span><span class=\"o\">.</span><span class=\"n\">update</span><span class=\"p\">(</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">formfield</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">defaults</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Nous partons du principe que la classe de champ <code class=\"docutils literal notranslate\"><span class=\"pre\">MyFormField</span></code> a été importée (elle possède son propre composant par défaut). Ce document ne traite pas en détails de l’écriture de champs de formulaires personnalisés.</p>\n</section>\n<section id=\"emulating-built-in-field-types\">\n<span id=\"id6\"></span><h4>Émulation de types de champs intégrés<a class=\"heading-anchor\" href=\"#emulating-built-in-field-types\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Si vous avez créé une méthode <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_type\" title=\"django.db.models.Field.db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">db_type()</span></code></a>, pas besoin de vous préoccuper de <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.get_internal_type\" title=\"django.db.models.Field.get_internal_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_internal_type()</span></code></a>, elle ne sera que peu utilisée. Il peut cependant arriver que le stockage de votre base de données a un même type qu’un autre champ, vous pouvez donc réutiliser la logique de ce dernier pour créer la bonne colonne.</p>\n<p>Par exemple :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">HandField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_internal_type</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;CharField&#39;</span>\n</code></pre></div>\n<p>Quel que soit le moteur de base de données utilisé, cela signifie que <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> et les autres commandes SQL créeront le bon type de colonne pour le stockage d’une chaîne.</p>\n<p>Si <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.get_internal_type\" title=\"django.db.models.Field.get_internal_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_internal_type()</span></code></a> renvoie une chaîne qui n’est pas connu de Django pour le moteur de base de données que vous utilisez – autrement dit, qu’il n’apparaît pas dans <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.backends.&lt;db_name&gt;.base.DatabaseWrapper.data_types</span></code> – la chaîne sera quand même utilisée par le sérialiseur, mais la méthode par défaut <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_type\" title=\"django.db.models.Field.db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">db_type()</span></code></a> retournera <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>. Consultez la documentation de <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.db_type\" title=\"django.db.models.Field.db_type\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">db_type()</span></code></a> pour les raisons pour lesquelles cela pourrait être utile. Mettre une chaîne descriptive dans le type du champ pour la sérialisation est une idée utile si vous devez un jour utiliser la sortie de sérialisation à un autre endroit, en dehors de Django.</p>\n</section>\n<section id=\"converting-field-data-for-serialization\">\n<span id=\"converting-model-field-to-serialization\"></span><h4>Conversion des données de champs pour la sérialisation<a class=\"heading-anchor\" href=\"#converting-field-data-for-serialization\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Pour personnaliser la façon dont les valeurs sont sérialisés par un sérialiseur, vous pouvez surcharger <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.value_to_string\" title=\"django.db.models.Field.value_to_string\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">value_to_string()</span></code></a>. L’appel à <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.value_from_object\" title=\"django.db.models.Field.value_from_object\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">value_from_object()</span></code></a> est le meilleur moyen d’obtenir la valeur du champ avant sa sérialisation. Par exemple, comme par ailleurs le champ <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code> utilise des chaînes pour le stockage de ses données, nous pouvons réutiliser du code existant de conversion :</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\">HandField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">value_to_string</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">obj</span><span class=\"p\">):</span>\n        <span class=\"n\">value</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">value_from_object</span><span class=\"p\">(</span><span class=\"n\">obj</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_prep_value</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"some-general-advice\">\n<h3>Quelques conseils généraux<a class=\"heading-anchor\" href=\"#some-general-advice\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>L’écriture d’un champ personnalisé peut être un processus fastidieux, particulièrement si vous procédez à des conversions complexes entre vos types Python et les formats de base de données et de sérialisation. Voici quelques astuces qui faciliteront ces opérations :</p>\n<ol class=\"arabic simple\">\n<li><p>Observez les champs Django existants (dans <code class=\"file docutils literal notranslate\"><span class=\"pre\">django/db/models/fields/__init__.py</span></code>) comme source d’inspiration. Cherchez un champ qui ressemble à ce que vous voulez faire et complétez ce qui manque, au lieu de créer un tout nouveau champ à partir de zéro.</p></li>\n<li><p>Écrivez une méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__str__()</span></code> pour la classe de champ que vous rédigez. À beaucoup d’endroits, le comportement par défaut du code du champ est d’appeler <code class=\"docutils literal notranslate\"><span class=\"pre\">str()</span></code> sur la valeur (dans les exemples de ce document, <code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> serait une instance <code class=\"docutils literal notranslate\"><span class=\"pre\">Hand</span></code>, pas <code class=\"docutils literal notranslate\"><span class=\"pre\">HandField</span></code>). Ainsi, si votre méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">__str__()</span></code> convertit automatiquement l’objet Python sous sa forme textuelle, vous économiserez beaucoup de travail.</p></li>\n</ol>\n</section>\n</section>\n<section id=\"writing-a-filefield-subclass\">\n<h2>Écriture d’une sous-classe<a class=\"heading-anchor\" href=\"#writing-a-filefield-subclass\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>En plus des méthodes ci-dessus, les champs qui manipulent des fichiers doivent répondre à quelques exigences supplémentaires dont il faut tenir compte. La plupart des mécanismes fournis par <code class=\"docutils literal notranslate\"><span class=\"pre\">FileField</span></code>, comme la maîtrise du stockage en base de données et de la récupération des données, peuvent rester tels quels ; il reste donc aux sous-classes la tâche pas toujours triviale de s’occuper de la prise en charge d’un type particulier de fichier.</p>\n<p>Django propose une classe <code class=\"docutils literal notranslate\"><span class=\"pre\">File</span></code> utilisée comme intermédiaire et chargée de s’occuper des contenus des fichiers et de leurs opérations. Elle peut être la base de sous-classes qui peuvent personnaliser l’accès au fichier et les méthodes disponibles. Elle se trouve dans <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.models.fields.files</span></code> et son comportement par défaut est expliqué dans la <a class=\"reference internal\" href=\"/fr/3.2/ref/files/file/\"><span class=\"doc\">documentation sur les fichiers</span></a>.</p>\n<p>Quand une sous-classe de <code class=\"docutils literal notranslate\"><span class=\"pre\">File</span></code> a été créée, il s’agit d’indiquer à la nouvelle sous-classe de <code class=\"docutils literal notranslate\"><span class=\"pre\">FileField</span></code> qu’elle doit l’utiliser. Pour cela, définissez la nouvelle sous-classe de <code class=\"docutils literal notranslate\"><span class=\"pre\">File</span></code> dans l’attribut spécial <code class=\"docutils literal notranslate\"><span class=\"pre\">attr_class</span></code> de la sous-classe de <code class=\"docutils literal notranslate\"><span class=\"pre\">FileField</span></code>.</p>\n<section id=\"a-few-suggestions\">\n<h3>Quelques suggestions<a class=\"heading-anchor\" href=\"#a-few-suggestions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>En plus des détails ci-dessus, voici quelques lignes de conduite qui peuvent grandement améliorer l’efficacité et la lisibilité du code du champ.</p>\n<ol class=\"arabic simple\">\n<li><p>Le code source du champ <code class=\"docutils literal notranslate\"><span class=\"pre\">ImageField</span></code> de Django (dans <code class=\"docutils literal notranslate\"><span class=\"pre\">django/db/models/fields/files.py</span></code>) est un très bon exemple de la manière dont une sous-classe de <code class=\"docutils literal notranslate\"><span class=\"pre\">FileField</span></code> peut prendre en charge un type particulier de fichier, car elle tient compte de toutes les techniques décrites ci-dessus.</p></li>\n<li><p>Mettez si possible en cache les attributs de fichier. Comme les fichiers peuvent être stockés sur des systèmes distants, leur accès peut impliquer des coûts de temps ou même financiers, ce qui n’est pas toujours nécessaire. Dès qu’un fichier est récupéré pour obtenir certaines informations sur son contenu, mettez le plus possible de ces données en cache pour réduire le nombre d’accès au fichier qui pourraient se produire lors d’éventuelles demandes futures pour ces mêmes informations.</p></li>\n</ol>\n</section>\n</section>","rootId":"writing-custom-model-fields","toc":[{"title":"Introduction","anchor":"introduction","children":[{"title":"Notre exemple d’objet","anchor":"our-example-object","children":[]}]},{"title":"Contexte théorique","anchor":"background-theory","children":[{"title":"Stockage de base de données","anchor":"database-storage","children":[]},{"title":"Que fait une classe de champ ?","anchor":"what-does-a-field-class-do","children":[]}]},{"title":"Écriture d’une sous-classe de champ","anchor":"writing-a-field-subclass","children":[{"title":"Déconstruction de champ","anchor":"field-deconstruction","children":[]},{"title":"Modification de la classe de base d’un champ personnalisé","anchor":"changing-a-custom-field-s-base-class","children":[]},{"title":"Documentation du champ personnalisé","anchor":"documenting-your-custom-field","children":[]},{"title":"Méthodes utiles","anchor":"useful-methods","children":[{"title":"Types de base de données personnalisés","anchor":"custom-database-types","children":[]},{"title":"Conversion de valeurs en objets Python","anchor":"converting-values-to-python-objects","children":[]},{"title":"Conversion d’objets Python en valeurs de requête","anchor":"converting-python-objects-to-query-values","children":[]},{"title":"Conversion de valeurs de requête en valeurs de base de données","anchor":"converting-query-values-to-database-values","children":[]},{"title":"Pré-traitement des valeurs avant enregistrement","anchor":"preprocessing-values-before-saving","children":[]},{"title":"Sélection du champ de formulaire pour un champ de modèle","anchor":"specifying-the-form-field-for-a-model-field","children":[]},{"title":"Émulation de types de champs intégrés","anchor":"emulating-built-in-field-types","children":[]},{"title":"Conversion des données de champs pour la sérialisation","anchor":"converting-field-data-for-serialization","children":[]}]},{"title":"Quelques conseils généraux","anchor":"some-general-advice","children":[]}]},{"title":"Écriture d’une sous-classe","anchor":"writing-a-filefield-subclass","children":[{"title":"Quelques suggestions","anchor":"a-few-suggestions","children":[]}]}],"breadcrumbs":[{"docname":"howto/index","title":"Guides pratiques","url":"/fr/3.2/howto/"}],"prev":{"docname":"howto/custom-management-commands","title":"Écriture de commandes django-admin personnalisées","url":"/fr/3.2/howto/custom-management-commands/"},"next":{"docname":"howto/custom-lookups","title":"Expressions de recherche personnalisées","url":"/fr/3.2/howto/custom-lookups/"},"formats":{"html":"/fr/3.2/howto/custom-model-fields/","markdown":"/fr/3.2/howto/custom-model-fields.md","json":"/fr/3.2/howto/custom-model-fields.json"},"source":"https://github.com/django/django/blob/stable/3.2.x/docs/howto/custom-model-fields.txt","official":"https://docs.djangoproject.com/fr/3.2/howto/custom-model-fields/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}