{"title":"Création de formulaires à partir de modèles","version":"6.0","locale":"fr","docname":"topics/forms/modelforms","url":"/fr/6.0/topics/forms/modelforms/","canonical":"https://djangodocs.dev/fr/6.0/topics/forms/modelforms/","summary":"Si vous construisez une application basée sur une base de données, il y a des chances pour que vos formulaires correspondent étroitement avec les modèles…","html":"<h1>Création de formulaires à partir de modèles<a class=\"heading-anchor\" href=\"#creating-forms-from-models\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<section id=\"modelform\">\n<h2><code class=\"docutils literal notranslate\">ModelForm</code><a class=\"heading-anchor\" href=\"#modelform\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.forms.ModelForm\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-name descname\">ModelForm</span><a class=\"heading-anchor\" href=\"#django.forms.ModelForm\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Si vous construisez une application basée sur une base de données, il y a des chances pour que vos formulaires correspondent étroitement avec les modèles Django. Par exemple, vous pourriez avoir un modèle <code class=\"docutils literal notranslate\">BlogComment</code> et vouloir créer un formulaire permettant d’envoyer des commentaires. Dans ce cas, il serait redondant de devoir définir les types de champs du formulaire, car vous avez déjà défini des champs au niveau du modèle.</p>\n<p>C’est pour cette raison que Django fournit une classe utilitaire permettant de créer une classe de formulaire <code class=\"docutils literal notranslate\">Form</code> à partir d’un modèle Django.</p>\n<p>Par exemple :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Article\n\n<span class=\"go\"># Create the form class.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">class</span> <span class=\"nc\">ArticleForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n<span class=\"gp\">... </span>    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n<span class=\"gp\">... </span>        model <span class=\"o\">=</span> Article\n<span class=\"gp\">... </span>        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;pub_date&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;content&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;reporter&quot;</span><span class=\"p\">]</span>\n<span class=\"gp\">...</span>\n\n<span class=\"go\"># Creating a form to add an article.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>form <span class=\"o\">=</span> ArticleForm<span class=\"p\">()</span>\n\n<span class=\"go\"># Creating a form to change an existing article.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>article <span class=\"o\">=</span> Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>pk<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>form <span class=\"o\">=</span> ArticleForm<span class=\"p\">(</span>instance<span class=\"o\">=</span>article<span class=\"p\">)</span>\n</code></pre></div>\n<section id=\"field-types\">\n<span id=\"model-form-field-types\"></span><h3>Types de champs<a class=\"heading-anchor\" href=\"#field-types\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>La classe de formulaire générée contiendra un champ de formulaire pour chaque champ de modèle inclus, dans l’ordre indiqué par l’attribut <code class=\"docutils literal notranslate\">fields</code>.</p>\n<p>Chaque champ de modèle possède un champ de formulaire par défaut. Par exemple, le champ <code class=\"docutils literal notranslate\">CharField</code> d’un modèle est représenté par un champ de formulaire <code class=\"docutils literal notranslate\">CharField</code>. Un champ <code class=\"docutils literal notranslate\">ManyToManyField</code> d’un modèle est représenté par un champ de formulaire <code class=\"docutils literal notranslate\">MultipleChoiceField</code>. Voici la liste complète des correspondances :</p>\n<div class=\"table-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"Table\"><table class=\"docutils align-default\">\n<thead>\n<tr class=\"row-odd\"><th class=\"head\"><p>Champ de modèle</p></th>\n<th class=\"head\"><p>Champ de formulaire</p></th>\n</tr>\n</thead>\n<tbody>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\">AutoField</code></a></p></td>\n<td><p>Non représenté dans le formulaire</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.BigAutoField\" title=\"django.db.models.BigAutoField\"><code class=\"xref py py-class docutils literal notranslate\">BigAutoField</code></a></p></td>\n<td><p>Non représenté dans le formulaire</p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.BigIntegerField\" title=\"django.db.models.BigIntegerField\"><code class=\"xref py py-class docutils literal notranslate\">BigIntegerField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.IntegerField\" title=\"django.forms.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a> avec <code class=\"docutils literal notranslate\">min_value</code> à -9223372036854775808 et <code class=\"docutils literal notranslate\">max_value</code> à 9223372036854775807.</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.BinaryField\" title=\"django.db.models.BinaryField\"><code class=\"xref py py-class docutils literal notranslate\">BinaryField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.CharField\" title=\"django.forms.CharField\"><code class=\"xref py py-class docutils literal notranslate\">CharField</code></a>, si <a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.Field.editable\" title=\"django.db.models.Field.editable\"><code class=\"xref py py-attr docutils literal notranslate\">editable</code></a> est défini à <code class=\"docutils literal notranslate\">True</code> sur le champ de modèle, sinon il n’est pas représenté dans le formulaire.</p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.BooleanField\" title=\"django.db.models.BooleanField\"><code class=\"xref py py-class docutils literal notranslate\">BooleanField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.BooleanField\" title=\"django.forms.BooleanField\"><code class=\"xref py py-class docutils literal notranslate\">BooleanField</code></a>, ou <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.NullBooleanField\" title=\"django.forms.NullBooleanField\"><code class=\"xref py py-class docutils literal notranslate\">NullBooleanField</code></a> si <code class=\"docutils literal notranslate\">null=True</code>.</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\">CharField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.CharField\" title=\"django.forms.CharField\"><code class=\"xref py py-class docutils literal notranslate\">CharField</code></a> avec <code class=\"docutils literal notranslate\">max_length</code> définie à la même valeur que <code class=\"docutils literal notranslate\">max_length</code> du champ de modèle et <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.CharField.empty_value\" title=\"django.forms.CharField.empty_value\"><code class=\"xref py py-attr docutils literal notranslate\">empty_value</code></a> définie à <code class=\"docutils literal notranslate\">None</code> si <code class=\"docutils literal notranslate\">null=True</code>.</p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.DateField\" title=\"django.db.models.DateField\"><code class=\"xref py py-class docutils literal notranslate\">DateField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.DateField\" title=\"django.forms.DateField\"><code class=\"xref py py-class docutils literal notranslate\">DateField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\">DateTimeField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.DateTimeField\" title=\"django.forms.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\">DateTimeField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.DecimalField\" title=\"django.db.models.DecimalField\"><code class=\"xref py py-class docutils literal notranslate\">DecimalField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.DecimalField\" title=\"django.forms.DecimalField\"><code class=\"xref py py-class docutils literal notranslate\">DecimalField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.DurationField\" title=\"django.db.models.DurationField\"><code class=\"xref py py-class docutils literal notranslate\">DurationField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.DurationField\" title=\"django.forms.DurationField\"><code class=\"xref py py-class docutils literal notranslate\">DurationField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.EmailField\" title=\"django.db.models.EmailField\"><code class=\"xref py py-class docutils literal notranslate\">EmailField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.EmailField\" title=\"django.forms.EmailField\"><code class=\"xref py py-class docutils literal notranslate\">EmailField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.FileField\" title=\"django.db.models.FileField\"><code class=\"xref py py-class docutils literal notranslate\">FileField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.FileField\" title=\"django.forms.FileField\"><code class=\"xref py py-class docutils literal notranslate\">FileField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.FilePathField\" title=\"django.db.models.FilePathField\"><code class=\"xref py py-class docutils literal notranslate\">FilePathField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.FilePathField\" title=\"django.forms.FilePathField\"><code class=\"xref py py-class docutils literal notranslate\">FilePathField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.FloatField\" title=\"django.db.models.FloatField\"><code class=\"xref py py-class docutils literal notranslate\">FloatField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.FloatField\" title=\"django.forms.FloatField\"><code class=\"xref py py-class docutils literal notranslate\">FloatField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\">ForeignKey</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.ModelChoiceField\" title=\"django.forms.ModelChoiceField\"><code class=\"xref py py-class docutils literal notranslate\">ModelChoiceField</code></a> (voir ci-dessous)</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.ImageField\" title=\"django.db.models.ImageField\"><code class=\"xref py py-class docutils literal notranslate\">ImageField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.ImageField\" title=\"django.forms.ImageField\"><code class=\"xref py py-class docutils literal notranslate\">ImageField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.IntegerField\" title=\"django.db.models.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.IntegerField\" title=\"django.forms.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><code class=\"docutils literal notranslate\">IPAddressField</code></p></td>\n<td><p><code class=\"docutils literal notranslate\">IPAddressField</code></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.GenericIPAddressField\" title=\"django.db.models.GenericIPAddressField\"><code class=\"xref py py-class docutils literal notranslate\">GenericIPAddressField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.GenericIPAddressField\" title=\"django.forms.GenericIPAddressField\"><code class=\"xref py py-class docutils literal notranslate\">GenericIPAddressField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.JSONField\" title=\"django.db.models.JSONField\"><code class=\"xref py py-class docutils literal notranslate\">JSONField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.JSONField\" title=\"django.forms.JSONField\"><code class=\"xref py py-class docutils literal notranslate\">JSONField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.ModelMultipleChoiceField\" title=\"django.forms.ModelMultipleChoiceField\"><code class=\"xref py py-class docutils literal notranslate\">ModelMultipleChoiceField</code></a> (voir ci-dessous)</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.PositiveBigIntegerField\" title=\"django.db.models.PositiveBigIntegerField\"><code class=\"xref py py-class docutils literal notranslate\">PositiveBigIntegerField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.IntegerField\" title=\"django.forms.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.PositiveIntegerField\" title=\"django.db.models.PositiveIntegerField\"><code class=\"xref py py-class docutils literal notranslate\">PositiveIntegerField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.IntegerField\" title=\"django.forms.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.PositiveSmallIntegerField\" title=\"django.db.models.PositiveSmallIntegerField\"><code class=\"xref py py-class docutils literal notranslate\">PositiveSmallIntegerField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.IntegerField\" title=\"django.forms.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.SlugField\" title=\"django.db.models.SlugField\"><code class=\"xref py py-class docutils literal notranslate\">SlugField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.SlugField\" title=\"django.forms.SlugField\"><code class=\"xref py py-class docutils literal notranslate\">SlugField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.SmallAutoField\" title=\"django.db.models.SmallAutoField\"><code class=\"xref py py-class docutils literal notranslate\">SmallAutoField</code></a></p></td>\n<td><p>Non représenté dans le formulaire</p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.SmallIntegerField\" title=\"django.db.models.SmallIntegerField\"><code class=\"xref py py-class docutils literal notranslate\">SmallIntegerField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.IntegerField\" title=\"django.forms.IntegerField\"><code class=\"xref py py-class docutils literal notranslate\">IntegerField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.TextField\" title=\"django.db.models.TextField\"><code class=\"xref py py-class docutils literal notranslate\">TextField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.CharField\" title=\"django.forms.CharField\"><code class=\"xref py py-class docutils literal notranslate\">CharField</code></a> avec <code class=\"docutils literal notranslate\">widget=forms.Textarea</code></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.TimeField\" title=\"django.db.models.TimeField\"><code class=\"xref py py-class docutils literal notranslate\">TimeField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.TimeField\" title=\"django.forms.TimeField\"><code class=\"xref py py-class docutils literal notranslate\">TimeField</code></a></p></td>\n</tr>\n<tr class=\"row-odd\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.URLField\" title=\"django.db.models.URLField\"><code class=\"xref py py-class docutils literal notranslate\">URLField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.URLField\" title=\"django.forms.URLField\"><code class=\"xref py py-class docutils literal notranslate\">URLField</code></a></p></td>\n</tr>\n<tr class=\"row-even\"><td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.UUIDField\" title=\"django.db.models.UUIDField\"><code class=\"xref py py-class docutils literal notranslate\">UUIDField</code></a></p></td>\n<td><p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.UUIDField\" title=\"django.forms.UUIDField\"><code class=\"xref py py-class docutils literal notranslate\">UUIDField</code></a></p></td>\n</tr>\n</tbody>\n</table>\n</div>\n<p>Comme l’on peut s’y attendre, les champs de modèle de type <code class=\"docutils literal notranslate\">ForeignKey</code> et <code class=\"docutils literal notranslate\">ManyToManyField</code> sont des cas spéciaux :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">ForeignKey</code> est représenté par <code class=\"docutils literal notranslate\">django.forms.ModelChoiceField</code>, qui est un champ <code class=\"docutils literal notranslate\">ChoiceField</code>  dont les choix possibles sont définis par le <code class=\"docutils literal notranslate\">QuerySet</code> d’un modèle.</p></li>\n<li><p><code class=\"docutils literal notranslate\">ManyToManyField</code> est représenté par un <code class=\"docutils literal notranslate\">django.forms.ModelMultipleChoiceField</code>, qui est un champ <code class=\"docutils literal notranslate\">MultipleChoiceField</code> dont les choix possibles sont définis par le <code class=\"docutils literal notranslate\">QuerySet</code> d’un modèle.</p></li>\n</ul>\n<p>De plus, chaque champ de formulaire généré possède les attributs comme suit :</p>\n<ul class=\"simple\">\n<li><p>Si le champ de modèle a <code class=\"docutils literal notranslate\">blank=True</code>, <code class=\"docutils literal notranslate\">required</code> est alors défini à <code class=\"docutils literal notranslate\">False</code> dans le champ de formulaire. Sinon, <code class=\"docutils literal notranslate\">required=True</code>.</p></li>\n<li><p>L’étiquette (<code class=\"docutils literal notranslate\">label</code>) du champ de formulaire est défini à la valeur <code class=\"docutils literal notranslate\">verbose_name</code> du champ de modèle, avec le premier caractère en majuscules.</p></li>\n<li><p>La valeur <code class=\"docutils literal notranslate\">help_text</code> du champ de formulaire est définie à la valeur <code class=\"docutils literal notranslate\">help_text</code> du champ de modèle.</p></li>\n<li><p>Si la valeur <code class=\"docutils literal notranslate\">choices</code> d’un champ de modèle est définie, le composant ( <code class=\"docutils literal notranslate\">widget</code>) du champ de formulaire sera de type <code class=\"docutils literal notranslate\">Select</code> dont les choix proviendront de la valeur <code class=\"docutils literal notranslate\">choices</code> du champ de modèle. Ces choix incluent normalement le choix vierge qui est sélectionné par défaut. Si le champ est obligatoire, cela force l’utilisateur à faire un choix. Le choix vierge n’est pas inclus si le champ de modèle a <code class=\"docutils literal notranslate\">blank=False</code> ainsi qu’une valeur par défaut (<code class=\"docutils literal notranslate\">default</code>) explicite (c’est la valeur <code class=\"docutils literal notranslate\">default</code> qui sera initialement sélectionnée).</p></li>\n</ul>\n<p>Pour terminer, notez que vous pouvez surcharger le champ de formulaire utilisé pour un champ de modèle donné. Consultez <a class=\"reference internal\" href=\"#overriding-the-default-fields\">Surcharge des champs par défaut</a> ci-dessous.</p>\n</section>\n<section id=\"a-full-example\">\n<h3>Un exemple complet<a class=\"heading-anchor\" href=\"#a-full-example\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Considérez cet ensemble de modèles :</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=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n<span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm\n\nTITLE_CHOICES <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;MR&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Mr.&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;MRS&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Mrs.&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;MS&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Ms.&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">}</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Author</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n    title <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">3</span><span class=\"p\">,</span> choices<span class=\"o\">=</span>TITLE_CHOICES<span class=\"p\">)</span>\n    birth_date <span class=\"o\">=</span> models<span class=\"o\">.</span>DateField<span class=\"p\">(</span>blank<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span> null<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span>name\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Book</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n    authors <span class=\"o\">=</span> models<span class=\"o\">.</span>ManyToManyField<span class=\"p\">(</span>Author<span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AuthorForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Author\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;birth_date&quot;</span><span class=\"p\">]</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">BookForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Book\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;authors&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>Avec ces modèles, les sous-classes <code class=\"docutils literal notranslate\">ModelForm</code> ci-dessus seraient à peu près équivalentes à ceci (avec comme seule différence la méthode <code class=\"docutils literal notranslate\">save()</code> que nous aborderons dans un moment) :</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=\"nn\">django</span> <span class=\"kn\">import</span> forms\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AuthorForm</span><span class=\"p\">(</span>forms<span class=\"o\">.</span>Form<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> forms<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n    title <span class=\"o\">=</span> forms<span class=\"o\">.</span>CharField<span class=\"p\">(</span>\n        max_length<span class=\"o\">=</span><span class=\"mi\">3</span><span class=\"p\">,</span>\n        widget<span class=\"o\">=</span>forms<span class=\"o\">.</span>Select<span class=\"p\">(</span>choices<span class=\"o\">=</span>TITLE_CHOICES<span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n    birth_date <span class=\"o\">=</span> forms<span class=\"o\">.</span>DateField<span class=\"p\">(</span>required<span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">BookForm</span><span class=\"p\">(</span>forms<span class=\"o\">.</span>Form<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> forms<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n    authors <span class=\"o\">=</span> forms<span class=\"o\">.</span>ModelMultipleChoiceField<span class=\"p\">(</span>queryset<span class=\"o\">=</span>Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">())</span>\n</code></pre></div>\n</section>\n<section id=\"validation-on-a-modelform\">\n<span id=\"validation-on-modelform\"></span><h3>Validation d’un <code class=\"docutils literal notranslate\">ModelForm</code><a class=\"heading-anchor\" href=\"#validation-on-a-modelform\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>La validation d’un <code class=\"docutils literal notranslate\">ModelForm</code> se distingue en deux étapes importantes :</p>\n<ol class=\"arabic simple\">\n<li><p>La <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/validation/\"><span class=\"doc\">validation du formulaire</span></a></p></li>\n<li><p>La <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#validating-objects\"><span class=\"std std-ref\">validation de l’instance de modèle</span></a></p></li>\n</ol>\n<p>Comme pour la validation de formulaire normale, la validation des formulaires de modèle est déclenchée implicitement lors de l’appel à <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/api/#django.forms.Form.is_valid\" title=\"django.forms.Form.is_valid\"><code class=\"xref py py-meth docutils literal notranslate\">is_valid()</code></a> ou par l’accession à l’attribut <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/api/#django.forms.Form.errors\" title=\"django.forms.Form.errors\"><code class=\"xref py py-attr docutils literal notranslate\">errors</code></a>, ou explicitement en appelant <code class=\"docutils literal notranslate\">full_clean()</code>, même si en pratique cette dernière méthode est rarement utilisée.</p>\n<p>La validation des modèles est déclenchée à partir de l’étape de validation de formulaire, juste après l’appel à la fonction <code class=\"docutils literal notranslate\">clean()</code> du formulaire. En premier, la méthode <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#django.db.models.Model.full_clean\" title=\"django.db.models.Model.full_clean\"><code class=\"xref py py-meth docutils literal notranslate\">full_clean()</code></a> du modèle est appelée avec <code class=\"docutils literal notranslate\">validate_unique=False</code> et <code class=\"docutils literal notranslate\">validate_constraints=False</code>, puis ce sont les méthodes <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#django.db.models.Model.validate_unique\" title=\"django.db.models.Model.validate_unique\"><code class=\"xref py py-meth docutils literal notranslate\">validate_unique()</code></a> et <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#django.db.models.Model.validate_constraints\" title=\"django.db.models.Model.validate_constraints\"><code class=\"xref py py-meth docutils literal notranslate\">validate_constraints()</code></a> qui sont appelées dans cet ordre.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Le processus de nettoyage modifie l’instance de modèle transmise au constructeur de <code class=\"docutils literal notranslate\">ModelForm</code> de plusieurs manières. Par exemple, toute valeur de champ date du modèle est convertie en vrai objet date. Une validation qui échoue peut laisser l’instance de modèle sous-jacente dans un état non cohérent et il n’est donc pas conseillé de la réutiliser.</p>\n</aside>\n<section id=\"overriding-the-clean-method\">\n<span id=\"overriding-modelform-clean-method\"></span><h4>Surcharge de la méthode <code class=\"docutils literal notranslate\">clean()</code><a class=\"heading-anchor\" href=\"#overriding-the-clean-method\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Vous pouvez surcharger la méthode <code class=\"docutils literal notranslate\">clean()</code> d’un formulaire de modèle pour procéder à des validations supplémentaires de la même manière que pour un formulaire normal.</p>\n<p>Une instance de formulaire de modèle liée à un objet modèle contient un attribut <code class=\"docutils literal notranslate\">instance</code> qui donne à ses méthodes l’accès à cette instance de modèle spécifique.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>La méthode <code class=\"docutils literal notranslate\">ModelForm.clean()</code> définit des drapeaux qui font que l’étape de <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#validating-objects\"><span class=\"std std-ref\">validation de modèle</span></a> valide l’unicité des champs de modèle marqués comme <code class=\"docutils literal notranslate\">unique</code>, <code class=\"docutils literal notranslate\">unique_together</code> ou <code class=\"docutils literal notranslate\">unique_for_date|month|year</code>, de même que les contraintes.</p>\n<p>Si vous souhaitez surcharger la méthode <code class=\"docutils literal notranslate\">clean()</code> et maintenir cette validation, vous devez appeler la méthode <code class=\"docutils literal notranslate\">clean()</code> de la classe parente.</p>\n</aside>\n</section>\n<section id=\"interaction-with-model-validation\">\n<h4>Interactions avec la validation des modèles<a class=\"heading-anchor\" href=\"#interaction-with-model-validation\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Dans le cadre du processus de validation, <code class=\"docutils literal notranslate\">ModelForm</code> appelle la méthode <code class=\"docutils literal notranslate\">clean()</code> de chaque champ du modèle possédant un champ de formulaire correspondant. Si vous avez exclu des champs de modèle, la validation ne sera pas effectuée pour ces champs. Consultez la documentation de la <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/validation/\"><span class=\"doc\">validation des formulaires</span></a> pour en savoir plus sur le fonctionnement du nettoyage et de la validation des champs.</p>\n<p>La méthode <code class=\"docutils literal notranslate\">clean()</code> du modèle est appelée avant les contrôles d’unicité et de contraintes. Consultez la <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#validating-objects\"><span class=\"std std-ref\">validation des objets</span></a> pour plus d’informations sur la méthode <code class=\"docutils literal notranslate\">clean()</code> des modèles.</p>\n</section>\n<section id=\"considerations-regarding-model-s-error-messages\">\n<span id=\"considerations-regarding-model-errormessages\"></span><h4>Considérations sur les messages d’erreur des modèles<a class=\"heading-anchor\" href=\"#considerations-regarding-model-s-error-messages\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Les messages d’erreur définis au niveau des <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/#django.forms.Field.error_messages\" title=\"django.forms.Field.error_messages\"><code class=\"xref py py-attr docutils literal notranslate\">champs de formulaire</code></a> ou au niveau de la <a class=\"reference internal\" href=\"#modelforms-overriding-default-fields\"><span class=\"std std-ref\">classe Meta de formulaire</span></a> ont toujours la priorité sur les messages d’erreur définis au niveau des <a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.Field.error_messages\" title=\"django.db.models.Field.error_messages\"><code class=\"xref py py-attr docutils literal notranslate\">champs de modèle</code></a>.</p>\n<p>Les messages d’erreur définis au niveau des <a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.Field.error_messages\" title=\"django.db.models.Field.error_messages\"><code class=\"xref py py-attr docutils literal notranslate\">champs de modèle</code></a> ne sont utilisés que lorsqu’une erreur <code class=\"docutils literal notranslate\">ValidationError</code> est générée à l’étape de <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#validating-objects\"><span class=\"std std-ref\">validation du modèle</span></a> et qu’aucun message d’erreur correspondant n’est défini au niveau du formulaire.</p>\n<p>Vous pouvez surcharger les messages d’erreur issus de <code class=\"docutils literal notranslate\">NON_FIELD_ERRORS</code> et générés par la validation des modèles en ajoutant la clé <a class=\"reference internal\" href=\"/fr/6.0/ref/exceptions/#django.core.exceptions.NON_FIELD_ERRORS\" title=\"django.core.exceptions.NON_FIELD_ERRORS\"><code class=\"xref py py-data docutils literal notranslate\">NON_FIELD_ERRORS</code></a> au dictionnaire <code class=\"docutils literal notranslate\">error_messages</code> de la classe <code class=\"docutils literal notranslate\">Meta</code> interne des classes <code class=\"docutils literal notranslate\">ModelForm</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\">from</span> <span class=\"nn\">django.core.exceptions</span> <span class=\"kn\">import</span> NON_FIELD_ERRORS\n<span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ArticleForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        error_messages <span class=\"o\">=</span> <span class=\"p\">{</span>\n            NON_FIELD_ERRORS<span class=\"p\">:</span> <span class=\"p\">{</span>\n                <span class=\"s2\">&quot;unique_together&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;</span><span class=\"si\">%(model_name)s</span><span class=\"s2\">&#39;s </span><span class=\"si\">%(field_labels)s</span><span class=\"s2\"> are not unique.&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">}</span>\n        <span class=\"p\">}</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"the-save-method\">\n<span id=\"topics-modelform-save\"></span><h3>La méthode <code class=\"docutils literal notranslate\">save()</code><a class=\"heading-anchor\" href=\"#the-save-method\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Chaque <code class=\"docutils literal notranslate\">ModelForm</code> possède aussi une méthode <code class=\"docutils literal notranslate\">save()</code>. Celle-ci crée et enregistre un objet en base de données à partir des données saisies dans le formulaire. Une sous-classe de <code class=\"docutils literal notranslate\">ModelForm</code> peut accepter une instance existante de modèle par le paramètre nommé <code class=\"docutils literal notranslate\">instance</code>. Si celui-ci est présent, <code class=\"docutils literal notranslate\">save()</code> met à jour cette instance. Dans le cas contraire, <code class=\"docutils literal notranslate\">save()</code> crée une nouvelle instance du modèle concerné :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Article\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">myapp.forms</span> <span class=\"kn\">import</span> ArticleForm\n\n<span class=\"go\"># Create a form instance from POST data.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>f <span class=\"o\">=</span> ArticleForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">)</span>\n\n<span class=\"go\"># Save a new Article object from the form&#39;s data.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article <span class=\"o\">=</span> f<span class=\"o\">.</span>save<span class=\"p\">()</span>\n\n<span class=\"go\"># Create a form to edit an existing Article, but use</span>\n<span class=\"go\"># POST data to populate the form.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>a <span class=\"o\">=</span> Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>pk<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>f <span class=\"o\">=</span> ArticleForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> instance<span class=\"o\">=</span>a<span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>f<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>Notez que si le formulaire <a class=\"reference internal\" href=\"#validation-on-modelform\"><span class=\"std std-ref\">n’a pas été validé</span></a>, l’appel à <code class=\"docutils literal notranslate\">save()</code> s’en occupera en contrôlant <code class=\"docutils literal notranslate\">form.errors</code>. Une erreur <code class=\"docutils literal notranslate\">ValueError</code> est générée si les données du formulaire ne sont pas valides, par exemple si <code class=\"docutils literal notranslate\">form.errors</code> est évalué à <code class=\"docutils literal notranslate\">True</code>.</p>\n<p>Si un champ facultatif ne figure pas dans les données de formulaire, l’instance de modèle résultante utilise comme valeur de champ le contenu <a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.Field.default\" title=\"django.db.models.Field.default\"><code class=\"xref py py-attr docutils literal notranslate\">default</code></a> du champ de modèle, si elle est définie. Ce comportement ne s’applique pas aux champs qui utilisent <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/widgets/#django.forms.CheckboxInput\" title=\"django.forms.CheckboxInput\"><code class=\"xref py py-class docutils literal notranslate\">CheckboxInput</code></a>, <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/widgets/#django.forms.CheckboxSelectMultiple\" title=\"django.forms.CheckboxSelectMultiple\"><code class=\"xref py py-class docutils literal notranslate\">CheckboxSelectMultiple</code></a> ou <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/widgets/#django.forms.SelectMultiple\" title=\"django.forms.SelectMultiple\"><code class=\"xref py py-class docutils literal notranslate\">SelectMultiple</code></a> (ou tout autre composant personnalisé dont la méthode  <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/widgets/#django.forms.Widget.value_omitted_from_data\" title=\"django.forms.Widget.value_omitted_from_data\"><code class=\"xref py py-meth docutils literal notranslate\">value_omitted_from_data()</code></a> renvoie toujours <code class=\"docutils literal notranslate\">False</code>) dans la mesure où une case à cocher non cochée ou des <code class=\"docutils literal notranslate\">&lt;select multiple&gt;</code> non sélectionnés ne sont pas inclus dans l’envoi des données d’un formulaire HTML. Utilisez un champ ou un composant de formulaire personnalisé si vous concevez une API et que vous souhaitez obtenir le comportement de valeur par défaut de base pour un champ qui utilise l’un de ces composants.</p>\n<p>Cette méthode <code class=\"docutils literal notranslate\">save()</code> accepte un paramètre nommé facultatif <code class=\"docutils literal notranslate\">commit</code>, qui accepte les valeurs <code class=\"docutils literal notranslate\">True</code> ou <code class=\"docutils literal notranslate\">False</code>. Si vous appelez <code class=\"docutils literal notranslate\">save()</code> avec <code class=\"docutils literal notranslate\">commit=False</code>, elle renvoie un objet qui n’aura pas encore été enregistré dans la base de données. Dans ce cas, c’est à vous d’appeler <code class=\"docutils literal notranslate\">save()</code> sur l’instance de modèle obtenue. C’est utile lorsque vous souhaitez effectuer un traitement particulier sur l’objet avant qu’il soit enregistré, ou si vous voulez utiliser l’une des <a class=\"reference internal\" href=\"/fr/6.0/ref/models/instances/#ref-models-force-insert\"><span class=\"std std-ref\">options d’enregistrement de modèle</span></a> spécialisées. <code class=\"docutils literal notranslate\">commit</code> vaut <code class=\"docutils literal notranslate\">True</code> par défaut.</p>\n<p>Un autre effet de bord de l’utilisation de <code class=\"docutils literal notranslate\">commit=False</code> se voit lorsque le modèle possède une relation plusieurs-à-plusieurs vers un autre modèle. Dans ce cas, Django ne peut pas enregistrer immédiatement les données du formulaire de la relation plusieurs-à-plusieurs. La raison est qu’il n’est pas possible d’enregistrer des données plusieurs-à-plusieurs propres à une instance si celle-ci n’existe pas encore dans la base de données.</p>\n<p>Pour contourner ce problème, chaque fois que vous enregistrez un formulaire avec <code class=\"docutils literal notranslate\">commit=False</code>, Django ajoute une méthode <code class=\"docutils literal notranslate\">save_m2m()</code> à la sous-classe de votre <code class=\"docutils literal notranslate\">ModelForm</code>. Après avoir manuellement enregistré l’instance dérivée du formulaire, vous pouvez appeler <code class=\"docutils literal notranslate\">save_m2m()</code> pour enregistrer les données de formulaire de type plusieurs-à-plusieurs. Par exemple :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"go\"># Create a form instance with POST data.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>f <span class=\"o\">=</span> AuthorForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">)</span>\n\n<span class=\"go\"># Create, but don&#39;t save the new author instance.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_author <span class=\"o\">=</span> f<span class=\"o\">.</span>save<span class=\"p\">(</span>commit<span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n\n<span class=\"go\"># Modify the author in some way.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_author<span class=\"o\">.</span>some_field <span class=\"o\">=</span> <span class=\"s2\">&quot;some_value&quot;</span>\n\n<span class=\"go\"># Save the new instance.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_author<span class=\"o\">.</span>save<span class=\"p\">()</span>\n\n<span class=\"go\"># Now, save the many-to-many data for the form.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>f<span class=\"o\">.</span>save_m2m<span class=\"p\">()</span>\n</code></pre></div>\n<p>Il n’est utile d’appeler <code class=\"docutils literal notranslate\">save_m2m()</code> que si vous utilisez <code class=\"docutils literal notranslate\">save(commit=False)</code>. Lorsque vous appelez la méthode <code class=\"docutils literal notranslate\">save()</code> d’un formulaire, toutes les données, y compris les données plusieurs-à-plusieurs, sont enregistrées sans avoir besoin de faire quoi que ce soit d’autre. Par exemple :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"go\"># Create a form instance with POST data.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>a <span class=\"o\">=</span> Author<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>f <span class=\"o\">=</span> AuthorForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> instance<span class=\"o\">=</span>a<span class=\"p\">)</span>\n\n<span class=\"go\"># Create and save the new author instance. There&#39;s no need to do anything else.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_author <span class=\"o\">=</span> f<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>À part les méthodes <code class=\"docutils literal notranslate\">save()</code> et <code class=\"docutils literal notranslate\">save_m2m()</code>, un <code class=\"docutils literal notranslate\">ModelForm</code> fonctionne exactement de la même manière que tout autre formulaire <code class=\"docutils literal notranslate\">forms</code>. Par exemple, la méthode <code class=\"docutils literal notranslate\">is_valid()</code> est utilisée pour vérifier la validité, la méthode <code class=\"docutils literal notranslate\">is_multipart()</code> est utilisée pour déterminer si un formulaire nécessite un envoi de fichier <code class=\"docutils literal notranslate\">multipart</code> (et donc que <code class=\"docutils literal notranslate\">request.FILES</code> doit être transmis au formulaire), etc. Voir <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/api/#binding-uploaded-files\"><span class=\"std std-ref\">Liaison de fichiers téléversés avec un formulaire</span></a> pour plus d’informations.</p>\n</section>\n<section id=\"selecting-the-fields-to-use\">\n<span id=\"modelforms-selecting-fields\"></span><h3>Sélection des champs à utiliser<a class=\"heading-anchor\" href=\"#selecting-the-fields-to-use\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il est fortement recommandé de définir explicitement tous les champs qui doivent être présents dans le formulaire en utilisant l’attribut <code class=\"docutils literal notranslate\">fields</code>. Si vous ne le faites pas, cela peut facilement devenir source de problèmes de sécurité lorsqu’un formulaire permet à un utilisateur de définir certains champs de manière non prévue, particulièrement lorsqu’on ajoute de nouveaux champs à un modèle. En fonction de la façon dont le formulaire est affiché, il est même possible que le problème ne soit pas visible sur la page Web.</p>\n<p>Une autre approche est d’inclure automatiquement tous les champs ou d’en exclure certains. Mais à la base, cette approche est notoirement moins sécurisée et a déjà abouti à des failles sévères sur des sites web célèbres (par ex. <a class=\"reference external\" href=\"https://github.blog/2012-03-04-public-key-security-vulnerability-and-mitigation/\">GitHub</a>).</p>\n<p>Il existe toutefois deux raccourcis disponibles pour les cas où vous pouvez garantir que ces questions de sécurité ne s’appliquent pas à votre situation :</p>\n<ol class=\"arabic\">\n<li><p>Définir l’attribut <code class=\"docutils literal notranslate\">fields</code> à la valeur spéciale <code class=\"docutils literal notranslate\">'__all__'</code> pour indiquer que tous les champs du modèle doivent être utilisés. 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=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AuthorForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Author\n        fields <span class=\"o\">=</span> <span class=\"s2\">&quot;__all__&quot;</span>\n</code></pre></div>\n</li>\n<li><p>Définir l’attribut <code class=\"docutils literal notranslate\">exclude</code> de la classe interne <code class=\"docutils literal notranslate\">Meta</code> du <code class=\"docutils literal notranslate\">ModelForm</code> à une liste de champs à exclure du formulaire.</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=\"nc\">PartialAuthorForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Author\n        exclude <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;title&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>Comme le modèle <code class=\"docutils literal notranslate\">Author</code> possède les trois champs <code class=\"docutils literal notranslate\">name</code>, <code class=\"docutils literal notranslate\">title</code> et <code class=\"docutils literal notranslate\">birth_date</code>, nous nous retrouvons avec les champs <code class=\"docutils literal notranslate\">name</code> et <code class=\"docutils literal notranslate\">birth_date</code> affichés dans le formulaire.</p>\n</li>\n</ol>\n<p>Si l’une de ces techniques est employée, l’ordre d’apparition des champs dans le formulaire respecte l’ordre de définition des champs du modèle, avec les instances <code class=\"docutils literal notranslate\">ManyToManyField</code> apparaissant en dernier.</p>\n<p>De plus, Django applique la règle suivante : si vous définissez <code class=\"docutils literal notranslate\">editable=False</code> au niveau du champ de modèle, <em>tout</em> formulaire créé à partir du modèle via <code class=\"docutils literal notranslate\">ModelForm</code> ne contiendra pas ce champ.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Tout champ non inclus dans un formulaire par la logique ci-dessus ne sera pas touché par la méthode <code class=\"docutils literal notranslate\">save()</code> du formulaire. De même, si vous ajoutez manuellement dans un formulaire un champ initialement exclu, ce champ ne sera pas initialisé avec les données de l’instance de modèle.</p>\n<p>Django empêche toute tentative d’enregistrer un modèle incomplet. Si le modèle n’autorise pas les champs manquants à être vides et que ces champs n’ont pas de valeur par défaut, tout tentative d’appeler <code class=\"docutils literal notranslate\">save()</code> sur un <code class=\"docutils literal notranslate\">ModelForm</code> avec des champs manquants échouera. Pour éviter ce problème, vous devez créer une instance de modèle comportant des valeurs initiales pour les champs obligatoires manquants :</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>author <span class=\"o\">=</span> Author<span class=\"p\">(</span>title<span class=\"o\">=</span><span class=\"s2\">&quot;Mr&quot;</span><span class=\"p\">)</span>\nform <span class=\"o\">=</span> PartialAuthorForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> instance<span class=\"o\">=</span>author<span class=\"p\">)</span>\nform<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>Une variante est d’utiliser <code class=\"docutils literal notranslate\">save(commit=False)</code> et de définir manuellement les champs obligatoires supplémentaires :</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>form <span class=\"o\">=</span> PartialAuthorForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">)</span>\nauthor <span class=\"o\">=</span> form<span class=\"o\">.</span>save<span class=\"p\">(</span>commit<span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\nauthor<span class=\"o\">.</span>title <span class=\"o\">=</span> <span class=\"s2\">&quot;Mr&quot;</span>\nauthor<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>Consultez la <a class=\"reference internal\" href=\"#the-save-method\">section sur l’enregistrement des formulaires</a> pour plus de détails sur l’utilisation de <code class=\"docutils literal notranslate\">save(commit=False)</code>.</p>\n</aside>\n</section>\n<section id=\"overriding-the-default-fields\">\n<span id=\"modelforms-overriding-default-fields\"></span><h3>Surcharge des champs par défaut<a class=\"heading-anchor\" href=\"#overriding-the-default-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les types de champs par défaut, tels que décrits dans le tableau ci-dessus <a class=\"reference internal\" href=\"#field-types\">Types de champs</a>, sont des choix raisonnables. Si votre modèle contient un champ <code class=\"docutils literal notranslate\">DateField</code>, il est probable que vous vouliez représenter ce champ dans un formulaire par un champ de formulaire <code class=\"docutils literal notranslate\">DateField</code>. Mais <code class=\"docutils literal notranslate\">ModelForm</code> apporte la souplesse de pouvoir modifier le champ de formulaire pour un modèle défini.</p>\n<p>Pour indiquer un composant personnalisé pour un champ, utilisez l’attribut <code class=\"docutils literal notranslate\">widgets</code> de la classe <code class=\"docutils literal notranslate\">Meta</code> interne. Ce doit être un dictionnaire faisant correspondre les noms de champs à des classes ou des instances de composants.</p>\n<p>Par exemple, si vous voulez que le champ <code class=\"docutils literal notranslate\">CharField</code> de l’attribut <code class=\"docutils literal notranslate\">name</code> du modèle <code class=\"docutils literal notranslate\">Author</code> soit représenté par un composant <code class=\"docutils literal notranslate\">&lt;textarea&gt;</code> au lieu du composant <code class=\"docutils literal notranslate\">&lt;input type=&quot;text&quot;&gt;</code> par défaut, vous pouvez surcharger le composant du 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=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm<span class=\"p\">,</span> Textarea\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Author\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AuthorForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Author\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;birth_date&quot;</span><span class=\"p\">]</span>\n        widgets <span class=\"o\">=</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> Textarea<span class=\"p\">(</span>attrs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;cols&quot;</span><span class=\"p\">:</span> <span class=\"mi\">80</span><span class=\"p\">,</span> <span class=\"s2\">&quot;rows&quot;</span><span class=\"p\">:</span> <span class=\"mi\">20</span><span class=\"p\">}),</span>\n        <span class=\"p\">}</span>\n</code></pre></div>\n<p>Le dictionnaire <code class=\"docutils literal notranslate\">widgets</code> accepte soit des instances de composants (par ex.  <code class=\"docutils literal notranslate\">Textarea(...)</code>) ou des classes (par ex. <code class=\"docutils literal notranslate\">Textarea</code>). Notez que le dictionnaire <code class=\"docutils literal notranslate\">widgets</code> est ignoré pour les champs de modèles ayant un attribut <code class=\"docutils literal notranslate\">choices</code> non vide. Dans ce cas, vous devez surcharger le champ de formulaire pour indiquer un composant <code class=\"docutils literal notranslate\">widget</code> différent.</p>\n<p>De la même façon, vous pouvez indiquer les attributs <code class=\"docutils literal notranslate\">labels</code>, <code class=\"docutils literal notranslate\">help_texts</code> et <code class=\"docutils literal notranslate\">error_messages</code> de la classe interne <code class=\"docutils literal notranslate\">Meta</code> si vous avez besoin de personnaliser davantage un champ.</p>\n<p>Par exemple, si vous souhaitez personnaliser la formulation de tous les textes visibles pour l’utilisateur concernant le champ <code class=\"docutils literal notranslate\">name</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\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n\n<span class=\"k\">class</span> <span class=\"nc\">AuthorForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Author\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;birth_date&quot;</span><span class=\"p\">]</span>\n        labels <span class=\"o\">=</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;Writer&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">}</span>\n        help_texts <span class=\"o\">=</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;Some useful help text.&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">}</span>\n        error_messages <span class=\"o\">=</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n                <span class=\"s2\">&quot;max_length&quot;</span><span class=\"p\">:</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;This writer&#39;s name is too long.&quot;</span><span class=\"p\">),</span>\n            <span class=\"p\">},</span>\n        <span class=\"p\">}</span>\n</code></pre></div>\n<p>Vous pouvez aussi indiquer <code class=\"docutils literal notranslate\">field_classes</code> ou <code class=\"docutils literal notranslate\">formfield_callback</code> pour personnaliser le type des champs créés par le formulaire.</p>\n<p>Par exemple, si vous souhaitez utiliser <code class=\"docutils literal notranslate\">MySlugFormField</code> pour le champ <code class=\"docutils literal notranslate\">slug</code>, vous pourriez procéder 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=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Article\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ArticleForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Article\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;pub_date&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;content&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;reporter&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">]</span>\n        field_classes <span class=\"o\">=</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">:</span> MySlugFormField<span class=\"p\">,</span>\n        <span class=\"p\">}</span>\n</code></pre></div>\n<p>ou :</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=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Article\n\n\n<span class=\"k\">def</span> <span class=\"nf\">formfield_for_dbfield</span><span class=\"p\">(</span>db_field<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    <span class=\"k\">if</span> db_field<span class=\"o\">.</span>name <span class=\"o\">==</span> <span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> MySlugFormField<span class=\"p\">()</span>\n    <span class=\"k\">return</span> db_field<span class=\"o\">.</span>formfield<span class=\"p\">(</span><span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ArticleForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Article\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;pub_date&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;content&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;reporter&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">]</span>\n        formfield_callback <span class=\"o\">=</span> formfield_for_dbfield\n</code></pre></div>\n<p>Finalement, si vous souhaitez contrôler complètement un champ, y compris son type, ses validateurs, son caractère obligatoire, etc., vous pouvez le faire en définissant les champs de manière déclarative comme on le ferait pour un formulaire <code class=\"docutils literal notranslate\">Form</code> normal.</p>\n<p>Si vous souhaitez indiquer les validateurs d’un champ, vous pouvez le faire en définissant le champ de manière déclarative et en indiquant le paramètre <code class=\"docutils literal notranslate\">validators</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\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> CharField<span class=\"p\">,</span> ModelForm\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Article\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ArticleForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    slug <span class=\"o\">=</span> CharField<span class=\"p\">(</span>validators<span class=\"o\">=</span><span class=\"p\">[</span>validate_slug<span class=\"p\">])</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Article\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;pub_date&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;content&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;reporter&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Lorsque vous créez une instance de formulaire explicitement comme ceci, il est important de comprendre comment les formulaires de type <code class=\"docutils literal notranslate\">ModelForm</code> et <code class=\"docutils literal notranslate\">Form</code> sont liés.</p>\n<p><code class=\"docutils literal notranslate\">ModelForm</code> est comme un formulaire <code class=\"docutils literal notranslate\">Form</code> normal qui peut générer automatiquement certains champs. Les champs automatiquement générés dépendent du contenu de la classe <code class=\"docutils literal notranslate\">Meta</code> et des champs éventuellement définis de manière déclarative. Au fond, <code class=\"docutils literal notranslate\">ModelForm</code> va <strong>uniquement</strong> générer les champs qui sont <strong>absents</strong> du formulaire, ou en d’autres termes, les champs qui n’ont pas été définis déclarativement.</p>\n<p>Les champs définis déclarativement sont laissés tels quels, ce qui fait que toute personnalisation effectuée au niveau des attributs de <code class=\"docutils literal notranslate\">Meta</code>, tels que <code class=\"docutils literal notranslate\">widgets</code>, <code class=\"docutils literal notranslate\">labels</code>, <code class=\"docutils literal notranslate\">help_texts</code> ou <code class=\"docutils literal notranslate\">error_messages</code> est ignorée ; ces derniers ne s’appliquent qu’aux champs automatiquement générés.</p>\n<p>De même, les champs définis déclarativement ne dérivent pas leurs attributs comme <code class=\"docutils literal notranslate\">max_length</code> ou <code class=\"docutils literal notranslate\">required</code> du modèle correspondant. Si vous voulez conserver le comportement défini au niveau du modèle, vous devez définir les paramètres adéquats explicitement dans la déclaration du champ de formulaire.</p>\n<p>Par exemple, si le modèle <code class=\"docutils literal notranslate\">Article</code> 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=\"nc\">Article</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    headline <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>\n        max_length<span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">,</span>\n        null<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n        blank<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n        help_text<span class=\"o\">=</span><span class=\"s2\">&quot;Use puns liberally&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n    content <span class=\"o\">=</span> models<span class=\"o\">.</span>TextField<span class=\"p\">()</span>\n</code></pre></div>\n<p>et que vous vouliez effectuer une validation particulière pour <code class=\"docutils literal notranslate\">headline</code> tout en conservant les valeurs <code class=\"docutils literal notranslate\">blank</code> et <code class=\"docutils literal notranslate\">help_text</code> d’origine, voici comment vous pourriez définir <code class=\"docutils literal notranslate\">ArticleForm</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=\"nc\">ArticleForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n    headline <span class=\"o\">=</span> MyFormField<span class=\"p\">(</span>\n        max_length<span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">,</span>\n        required<span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">,</span>\n        help_text<span class=\"o\">=</span><span class=\"s2\">&quot;Use puns liberally&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Article\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;content&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>Vous devez vous assurer que le type du champ de formulaire peut être utilisé pour définir le contenu du champ de modèle correspondant. S’ils ne sont pas compatibles, vous obtiendrez une erreur <code class=\"docutils literal notranslate\">ValueError</code> car aucune conversion implicite n’est effectuée.</p>\n<p>Consultez la <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/fields/\"><span class=\"doc\">documentation des champs de formulaire</span></a> pour plus d’informations sur les champs et leurs paramètres.</p>\n</aside>\n</section>\n<section id=\"enabling-localization-of-fields\">\n<span id=\"modelforms-enabling-localization-of-fields\"></span><h3>Activation de la régionalisation des champs<a class=\"heading-anchor\" href=\"#enabling-localization-of-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Par défaut, les champs d’un <code class=\"docutils literal notranslate\">ModelForm</code> ne régionalisent pas leurs données. Pour activer cette régionalisation, vous pouvez utiliser l’attribut <code class=\"docutils literal notranslate\">localized_fields</code> de la classe <code class=\"docutils literal notranslate\">Meta</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=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> ModelForm\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Author\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">class</span> <span class=\"nc\">AuthorForm</span><span class=\"p\">(</span>ModelForm<span class=\"p\">):</span>\n<span class=\"gp\">... </span>    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n<span class=\"gp\">... </span>        model <span class=\"o\">=</span> Author\n<span class=\"gp\">... </span>        localized_fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;birth_date&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>Si <code class=\"docutils literal notranslate\">localized_fields</code> est défini à la valeur spéciale <code class=\"docutils literal notranslate\">'__all__'</code>, les valeurs de tous les champs seront régionalisées.</p>\n</section>\n<section id=\"form-inheritance\">\n<h3>Héritage de formulaire<a class=\"heading-anchor\" href=\"#form-inheritance\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme pour les formulaires de base, il est possible d’étendre et de réutiliser les classes <code class=\"docutils literal notranslate\">ModelForm</code> par l’héritage. C’est utile lorsque vous devez déclarer des champs ou des méthodes supplémentaires dans une sous-classe pour les utiliser dans des formulaires dérivés de modèles. Par exemple, en utilisant la classe <code class=\"docutils literal notranslate\">ArticleForm</code> présentée précédemment :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">class</span> <span class=\"nc\">EnhancedArticleForm</span><span class=\"p\">(</span>ArticleForm<span class=\"p\">):</span>\n<span class=\"gp\">... </span>    <span class=\"k\">def</span> <span class=\"nf\">clean_pub_date</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n<span class=\"gp\">...</span>\n</code></pre></div>\n<p>Cela crée un formulaire qui se comporte comme <code class=\"docutils literal notranslate\">ArticleForm</code>, à l’exception de certaines validations et nettoyages supplémentaires pour le champ <code class=\"docutils literal notranslate\">pub_date</code>.</p>\n<p>Il est aussi possible d’hériter de la classe <code class=\"docutils literal notranslate\">Meta</code> interne du parent si vous avez besoin de modifier les listes <code class=\"docutils literal notranslate\">Meta.fields</code> ou <code class=\"docutils literal notranslate\">Meta.exclude</code>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">class</span> <span class=\"nc\">RestrictedArticleForm</span><span class=\"p\">(</span>EnhancedArticleForm<span class=\"p\">):</span>\n<span class=\"gp\">... </span>    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">(</span>ArticleForm<span class=\"o\">.</span>Meta<span class=\"p\">):</span>\n<span class=\"gp\">... </span>        exclude <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;body&quot;</span><span class=\"p\">]</span>\n<span class=\"gp\">...</span>\n</code></pre></div>\n<p>Nous conservons ici la méthode supplémentaire de <code class=\"docutils literal notranslate\">EnhancedArticleForm</code> et enlevons un champ de la classe <code class=\"docutils literal notranslate\">ArticleForm.Meta</code> originale.</p>\n<p>Il faut cependant relever certains points.</p>\n<ul>\n<li><p>Les règles Python habituelles de la résolution de noms s’appliquent. Si vous avez plusieurs classes de base déclarant une classe interne <code class=\"docutils literal notranslate\">Meta</code>, seule la première sera considérée. C’est -à-dire la classe <code class=\"docutils literal notranslate\">Meta</code> de la sous-classe, s’il y en a une, sinon celle du premier parent, etc.</p></li>\n<li><p>Il est possible d’hériter à la fois de <code class=\"docutils literal notranslate\">Form</code> et de <code class=\"docutils literal notranslate\">ModelForm</code>. Cependant, il faut s’assurer que <code class=\"docutils literal notranslate\">ModelForm</code> apparaisse en premier dans la chaîne MRO. Ceci parce que ces classes se basent sur des métaclasses différentes et qu’une classe ne peut posséder qu’une seule métaclasse.</p></li>\n<li><p>Il est possible d’enlever de manière déclarative un champ <code class=\"docutils literal notranslate\">Field</code> hérité d’une classe parente en définissant son nom à <code class=\"docutils literal notranslate\">None</code> dans la sous-classe.</p>\n<p>Cette technique n’est utilisable que pour enlever des champs qui ont eux-mêmes été définis de manière déclarative dans la classe parente ; cela n’empêchera pas la métaclasse de <code class=\"docutils literal notranslate\">ModelForm</code> de générer un champ par défaut. Pour enlever des champs par défaut, voir <a class=\"reference internal\" href=\"#modelforms-selecting-fields\"><span class=\"std std-ref\">Sélection des champs à utiliser</span></a>.</p>\n</li>\n</ul>\n</section>\n<section id=\"providing-initial-values\">\n<h3>Indication de valeurs initiales<a class=\"heading-anchor\" href=\"#providing-initial-values\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme avec les formulaires normaux, il est possible de spécifier les données initiales pour les formulaires en spécifiant un paramètre <code class=\"docutils literal notranslate\">initial</code> lors de l’instanciation du formulaire. Les valeurs initiales prévues de cette façon remplaceront la valeur initiale définie pour le champ et celle définie pour le modèle lié. Par exemple :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>article <span class=\"o\">=</span> Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>pk<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>article<span class=\"o\">.</span>headline\n<span class=\"go\">&#39;My headline&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>form <span class=\"o\">=</span> ArticleForm<span class=\"p\">(</span>initial<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;Initial headline&quot;</span><span class=\"p\">},</span> instance<span class=\"o\">=</span>article<span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>form<span class=\"p\">[</span><span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">]</span><span class=\"o\">.</span>value<span class=\"p\">()</span>\n<span class=\"go\">&#39;Initial headline&#39;</span>\n</code></pre></div>\n</section>\n<section id=\"modelform-factory-function\">\n<span id=\"modelforms-factory\"></span><h3>Fonction de fabrique de ModelForm<a class=\"heading-anchor\" href=\"#modelform-factory-function\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Vous pouvez créer des formulaires à partir d’un modèle donné en utilisant la fonction autonome <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.modelform_factory\" title=\"django.forms.models.modelform_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelform_factory()</code></a> au lieu de passer par une définition de classe. Cela peut être plus pratique si vous n’avez pas à effectuer trop d’adaptations :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> modelform_factory\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Book\n<span class=\"gp\">&gt;&gt;&gt; </span>BookForm <span class=\"o\">=</span> modelform_factory<span class=\"p\">(</span>Book<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;author&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Cela peut également être utilisé pour faire des modifications à des formulaires existants, par exemple pour indiquer les composants à utiliser pour un certain champ :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> Textarea\n<span class=\"gp\">&gt;&gt;&gt; </span>Form <span class=\"o\">=</span> modelform_factory<span class=\"p\">(</span>Book<span class=\"p\">,</span> form<span class=\"o\">=</span>BookForm<span class=\"p\">,</span> widgets<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;title&quot;</span><span class=\"p\">:</span> Textarea<span class=\"p\">()})</span>\n</code></pre></div>\n<p>Les champs à inclure peuvent être spécifiés en utilisant les paramètres nommés <code class=\"docutils literal notranslate\">fields</code> et <code class=\"docutils literal notranslate\">exclude</code>, ou les attributs correspondants de la classe interne <code class=\"docutils literal notranslate\">Meta</code> du <code class=\"docutils literal notranslate\">ModelForm</code>. Veuillez consulter la documentation <a class=\"reference internal\" href=\"#modelforms-selecting-fields\"><span class=\"std std-ref\">Sélection des champs à utiliser</span></a> des <code class=\"docutils literal notranslate\">ModelForm</code>.</p>\n<p>… ou pour activer la régionalisation de certains champs :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Form <span class=\"o\">=</span> modelform_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> form<span class=\"o\">=</span>AuthorForm<span class=\"p\">,</span> localized_fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;birth_date&quot;</span><span class=\"p\">])</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"model-formsets\">\n<span id=\"id1\"></span><h2>Formulaires groupés de modèles<a class=\"heading-anchor\" href=\"#model-formsets\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.forms.models.BaseModelFormSet\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-prename descclassname\">models.</span><span class=\"sig-name descname\">BaseModelFormSet</span><a class=\"heading-anchor\" href=\"#django.forms.models.BaseModelFormSet\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Comme pour les <a class=\"reference internal\" href=\"/fr/6.0/topics/forms/formsets/\"><span class=\"doc\">formulaires groupés normaux</span></a>, Django fournit quelques classes de formulaires groupés améliorées qui facilitent le travail avec les modèles Django. Réutilisons le modèle <code class=\"docutils literal notranslate\">Author</code> défini plus haut :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> modelformset_factory\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Author\n<span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>L’utilisation de <code class=\"docutils literal notranslate\">fields</code> indique aux formulaires groupés  les champs qu’ils doivent utiliser. Il est aussi possible d’utiliser une approche par exclusion, indiquant quels sont les champs à exclure :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> exclude<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;birth_date&quot;</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Cela crée un jeu de formulaires groupés qui sont capables de gérer les données associées au modèle <code class=\"docutils literal notranslate\">Author</code>. Le fonctionnement est le même que pour des formulaires groupés normaux :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"nb\">print</span><span class=\"p\">(</span>formset<span class=\"p\">)</span>\n<span class=\"go\">&lt;input type=&quot;hidden&quot; name=&quot;form-TOTAL_FORMS&quot; value=&quot;1&quot; id=&quot;id_form-TOTAL_FORMS&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-INITIAL_FORMS&quot; value=&quot;0&quot; id=&quot;id_form-INITIAL_FORMS&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-MIN_NUM_FORMS&quot; value=&quot;0&quot; id=&quot;id_form-MIN_NUM_FORMS&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-MAX_NUM_FORMS&quot; value=&quot;1000&quot; id=&quot;id_form-MAX_NUM_FORMS&quot;&gt;</span>\n<span class=\"go\">&lt;div&gt;&lt;label for=&quot;id_form-0-name&quot;&gt;Name:&lt;/label&gt;&lt;input id=&quot;id_form-0-name&quot; type=&quot;text&quot; name=&quot;form-0-name&quot; maxlength=&quot;100&quot;&gt;&lt;/div&gt;</span>\n<span class=\"go\">&lt;div&gt;&lt;label for=&quot;id_form-0-title&quot;&gt;Title:&lt;/label&gt;&lt;select name=&quot;form-0-title&quot; id=&quot;id_form-0-title&quot;&gt;</span>\n<span class=\"go\">&lt;option value=&quot;&quot; selected&gt;---------&lt;/option&gt;</span>\n<span class=\"go\">&lt;option value=&quot;MR&quot;&gt;Mr.&lt;/option&gt;</span>\n<span class=\"go\">&lt;option value=&quot;MRS&quot;&gt;Mrs.&lt;/option&gt;</span>\n<span class=\"go\">&lt;option value=&quot;MS&quot;&gt;Ms.&lt;/option&gt;</span>\n<span class=\"go\">&lt;/select&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-0-id&quot; id=&quot;id_form-0-id&quot;&gt;&lt;/div&gt;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.modelformset_factory\" title=\"django.forms.models.modelformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelformset_factory()</code></a> utilise <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/formsets/#django.forms.formsets.formset_factory\" title=\"django.forms.formsets.formset_factory\"><code class=\"xref py py-func docutils literal notranslate\">formset_factory()</code></a> pour générer les formulaires groupés. Cela signifie qu’un formulaire groupé de modèle est une extension des formulaires groupés de base sachant interagir avec un modèle particulier.</p>\n</aside>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Dans les contextes d’<a class=\"reference internal\" href=\"/fr/6.0/topics/db/models/#multi-table-inheritance\"><span class=\"std std-ref\">héritages multi-tables</span></a>, les formulaires générés par une fabrique de jeux de formulaires contiennent un champ de lien parent (par défaut <code class=\"docutils literal notranslate\">&lt;nom_modèle_parent&gt;_ptr</code>) au lieu d’un champ <code class=\"docutils literal notranslate\">id</code>.</p>\n</aside>\n<section id=\"changing-the-queryset\">\n<h3>Modification du jeu de requête<a class=\"heading-anchor\" href=\"#changing-the-queryset\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Par défaut, lorsque vous créez des formulaires groupés à partir d’un modèle, ceux-ci utilisent un jeu de requête qui contient tous les objets du modèle (par ex. <code class=\"docutils literal notranslate\">Author.objects.all()</code>). Vous pouvez surcharger ce comportement en utilisant le paramètre <code class=\"docutils literal notranslate\">queryset</code>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">(</span>queryset<span class=\"o\">=</span>Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>name__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;O&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>Comme variante, vous pouvez créer une sous-classe définissant <code class=\"docutils literal notranslate\">self.queryset</code> dans sa méthode <code class=\"docutils literal notranslate\">__init__</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\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> BaseModelFormSet\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Author\n\n\n<span class=\"k\">class</span> <span class=\"nc\">BaseAuthorFormSet</span><span class=\"p\">(</span>BaseModelFormSet<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</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>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>queryset <span class=\"o\">=</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>name__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;O&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Puis, passez votre classe <code class=\"docutils literal notranslate\">BaseAuthorFormSet</code> à la fonction de fabrique :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    Author<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">],</span> formset<span class=\"o\">=</span>BaseAuthorFormSet\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Si vous souhaitez renvoyer des formulaires groupés qui ne contiennent <em>aucune</em> instance préexistante du modèle, vous pouvez indiquer un objet <code class=\"docutils literal notranslate\">QuerySet</code> vide :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet<span class=\"p\">(</span>queryset<span class=\"o\">=</span>Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>none<span class=\"p\">())</span>\n</code></pre></div>\n</section>\n<section id=\"changing-the-form\">\n<h3>Modification du formulaire<a class=\"heading-anchor\" href=\"#changing-the-form\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Par défaut, lorsque vous utilisez <code class=\"docutils literal notranslate\">modelformset_factory</code>, un formulaire de modèle est créé par <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.modelform_factory\" title=\"django.forms.models.modelform_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelform_factory()</code></a>. Il peut souvent être utile d’indiquer un formulaire de modèle personnalisé. Par exemple, vous pouvez créer un formulaire de modèle personnalisé comportant une validation personnalisée :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"nc\">AuthorForm</span><span class=\"p\">(</span>forms<span class=\"o\">.</span>ModelForm<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        model <span class=\"o\">=</span> Author\n        fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">]</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">clean_name</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># custom validation for the name field</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>Puis, indiquez ce formulaire de modèle à la fonction de fabrication :</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>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> form<span class=\"o\">=</span>AuthorForm<span class=\"p\">)</span>\n</code></pre></div>\n<p>Il n’est pas toujours nécessaire de définir un formulaire de modèle personnalisé. La fonction <code class=\"docutils literal notranslate\">modelformset_factory</code> accepte plusieurs paramètres qui sont eux-mêmes transmis à <code class=\"docutils literal notranslate\">modelform_factory</code> et qui sont documentés plus bas.</p>\n</section>\n<section id=\"specifying-widgets-to-use-in-the-form-with-widgets\">\n<h3>Indication des composants de formulaire à utiliser avec <code class=\"docutils literal notranslate\">widgets</code><a class=\"heading-anchor\" href=\"#specifying-widgets-to-use-in-the-form-with-widgets\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>En exploitant le paramètre <code class=\"docutils literal notranslate\">widgets</code>, vous pouvez indiquer un dictionnaire de valeurs afin de personnaliser la classe de composant d’un champ particulier du <code class=\"docutils literal notranslate\">ModelForm</code>. C’est le même principe de fonctionnement que le dictionnaire <code class=\"docutils literal notranslate\">widgets</code> de la classe <code class=\"docutils literal notranslate\">Meta</code> interne d’un <code class=\"docutils literal notranslate\">ModelForm</code>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    Author<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">],</span>\n<span class=\"gp\">... </span>    widgets<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> Textarea<span class=\"p\">(</span>attrs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;cols&quot;</span><span class=\"p\">:</span> <span class=\"mi\">80</span><span class=\"p\">,</span> <span class=\"s2\">&quot;rows&quot;</span><span class=\"p\">:</span> <span class=\"mi\">20</span><span class=\"p\">})},</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"enabling-localization-for-fields-with-localized-fields\">\n<h3>Activation de la régionalisation des champs avec <code class=\"docutils literal notranslate\">localized_fields</code><a class=\"heading-anchor\" href=\"#enabling-localization-for-fields-with-localized-fields\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>À l’aide du paramètre <code class=\"docutils literal notranslate\">localized_fields</code>, vous pouvez activer la régionalisation des champs du formulaire.</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    Author<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;title&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;birth_date&#39;</span><span class=\"p\">],</span>\n<span class=\"gp\">... </span>    localized_fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s1\">&#39;birth_date&#39;</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Si <code class=\"docutils literal notranslate\">localized_fields</code> est défini à la valeur spéciale <code class=\"docutils literal notranslate\">'__all__'</code>, les valeurs de tous les champs seront régionalisées.</p>\n</section>\n<section id=\"id2\">\n<h3>Indication de valeurs initiales<a class=\"heading-anchor\" href=\"#id2\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme pour les formulaires groupés normaux, il est possible <a class=\"reference internal\" href=\"/fr/6.0/topics/forms/formsets/#formsets-initial-data\"><span class=\"std std-ref\">de fournir des données initiales</span></a> aux formulaires groupés en indiquant le paramètre <code class=\"docutils literal notranslate\">initial</code> au moment de la création de l’instance de classe de formulaires groupés de modèles renvoyée par <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.modelformset_factory\" title=\"django.forms.models.modelformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelformset_factory()</code></a>. Cependant, avec les formulaires groupés de modèles, les valeurs initiales ne s’appliquent qu’aux formulaires supplémentaires, ceux qui ne sont pas liés à des instances d’objets existants. Si la longueur de <code class=\"docutils literal notranslate\">initial</code> dépasse le nombre de formulaires supplémentaires, les données initiales en trop sont ignorées. Si les formulaires supplémentaires avec données initiales ne sont pas modifiés par l’utilisateur, ils ne seront ni validés, ni enregistrés.</p>\n</section>\n<section id=\"saving-objects-in-the-formset\">\n<span id=\"id3\"></span><h3>Enregistrement des objets des formulaires groupés<a class=\"heading-anchor\" href=\"#saving-objects-in-the-formset\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme pour un <code class=\"docutils literal notranslate\">ModelForm</code>, vous pouvez enregistrer les données sous forme d’objet de modèle. Cela se fait par la méthode <code class=\"docutils literal notranslate\">save()</code> des formulaires groupés :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"go\"># Create a formset instance with POST data.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">)</span>\n\n<span class=\"go\"># Assuming all is valid, save the data.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>instances <span class=\"o\">=</span> formset<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>La méthode <code class=\"docutils literal notranslate\">save()</code> renvoie les instances qui ont été enregistrées dans la base de données. Si les données d’une instance précise n’ont pas été modifiées dans les données du formulaire, l’instance ne sera pas enregistrée dans la base de données et ne sera pas non plus incluse dans la valeur renvoyée (<code class=\"docutils literal notranslate\">instances</code>, dans l’exemple ci-dessus).</p>\n<p>Lorsque des champs sont absents du formulaire (par exemple en raison de leur exclusion), ces champs ne sont pas modifiés par la méthode <code class=\"docutils literal notranslate\">save()</code>. Vous pouvez trouver plus d’informations sur cette restriction, qui est aussi valable pour les formulaires de modèles normaux, dans <a class=\"reference internal\" href=\"#selecting-the-fields-to-use\">Sélection des champs à utiliser</a>.</p>\n<p>Passez <code class=\"docutils literal notranslate\">commit=False</code> pour recevoir les instances de modèles non enregistrées :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"go\"># don&#39;t save to the database</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>instances <span class=\"o\">=</span> formset<span class=\"o\">.</span>save<span class=\"p\">(</span>commit<span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">for</span> instance <span class=\"ow\">in</span> instances<span class=\"p\">:</span>\n<span class=\"gp\">... </span>    <span class=\"c1\"># do something with instance</span>\n<span class=\"gp\">... </span>    instance<span class=\"o\">.</span>save<span class=\"p\">()</span>\n<span class=\"gp\">...</span>\n</code></pre></div>\n<p>Cela vous permet de définir des données complémentaires dans les instances avant de les enregistrer dans la base de données. Si vos formulaires groupés contiennent un champ <code class=\"docutils literal notranslate\">ManyToManyField</code>, vous devrez également appeler <code class=\"docutils literal notranslate\">formset.save_m2m()</code> pour vous assurer que les liens plusieurs-à-plusieurs soient correctement enregistrés.</p>\n<p>Après l’appel à <code class=\"docutils literal notranslate\">save()</code>, les formulaires groupés du modèle posséderont trois nouveaux attributs contenant les modifications des formulaires :</p>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.forms.models.BaseModelFormSet.changed_objects\">\n<span class=\"sig-prename descclassname\">models.BaseModelFormSet.</span><span class=\"sig-name descname\">changed_objects</span><a class=\"heading-anchor\" href=\"#django.forms.models.BaseModelFormSet.changed_objects\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.forms.models.BaseModelFormSet.deleted_objects\">\n<span class=\"sig-prename descclassname\">models.BaseModelFormSet.</span><span class=\"sig-name descname\">deleted_objects</span><a class=\"heading-anchor\" href=\"#django.forms.models.BaseModelFormSet.deleted_objects\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.forms.models.BaseModelFormSet.new_objects\">\n<span class=\"sig-prename descclassname\">models.BaseModelFormSet.</span><span class=\"sig-name descname\">new_objects</span><a class=\"heading-anchor\" href=\"#django.forms.models.BaseModelFormSet.new_objects\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n</section>\n<section id=\"limiting-the-number-of-editable-objects\">\n<span id=\"model-formsets-max-num\"></span><h3>Restriction du nombre d’objets modifiables<a class=\"heading-anchor\" href=\"#limiting-the-number-of-editable-objects\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme pour les formulaires groupés normaux, vous pouvez utiliser les paramètres <code class=\"docutils literal notranslate\">max_num</code> et <code class=\"docutils literal notranslate\">extra</code> de <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.modelformset_factory\" title=\"django.forms.models.modelformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelformset_factory()</code></a> pour restreindre le nombre de formulaires supplémentaires affichés.</p>\n<p><code class=\"docutils literal notranslate\">max_num</code> n’empêche pas les objets existants d’être affichés :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<span class=\"p\">(</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Author: Charles Baudelaire&gt;, &lt;Author: Paul Verlaine&gt;, &lt;Author: Walt Whitman&gt;]&gt;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">],</span> max_num<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">(</span>queryset<span class=\"o\">=</span>Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<span class=\"p\">(</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"p\">[</span>x<span class=\"o\">.</span>name <span class=\"k\">for</span> x <span class=\"ow\">in</span> formset<span class=\"o\">.</span>get_queryset<span class=\"p\">()]</span>\n<span class=\"go\">[&#39;Charles Baudelaire&#39;, &#39;Paul Verlaine&#39;, &#39;Walt Whitman&#39;]</span>\n</code></pre></div>\n<p>De plus, <code class=\"docutils literal notranslate\">extra=0</code> n’empêche pas la création de nouvelles instances de modèles car il est possible <a class=\"reference internal\" href=\"/fr/6.0/topics/forms/formsets/#understanding-the-managementform\"><span class=\"std std-ref\">d’ajouter des formulaires supplémentaires par JavaScript</span></a> ou d’envoyer des données POST supplémentaires. Consultez <a class=\"reference internal\" href=\"#model-formsets-edit-only\"><span class=\"std std-ref\">Empêcher la création de nouveaux objets</span></a> pour voir la manière de faire cela.</p>\n<p>Si la valeur de <code class=\"docutils literal notranslate\">max_num</code> est plus grande que le nombre d’objets liés existants, un maximum de  <code class=\"docutils literal notranslate\">extra</code> formulaires vierges supplémentaires seront ajoutés aux formulaires groupés, aussi longtemps que le nombre total de formulaires n’excède pas <code class=\"docutils literal notranslate\">max_num</code>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">],</span> max_num<span class=\"o\">=</span><span class=\"mi\">4</span><span class=\"p\">,</span> extra<span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">(</span>queryset<span class=\"o\">=</span>Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<span class=\"p\">(</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">for</span> form <span class=\"ow\">in</span> formset<span class=\"p\">:</span>\n<span class=\"gp\">... </span>    <span class=\"nb\">print</span><span class=\"p\">(</span>form<span class=\"p\">)</span>\n<span class=\"gp\">...</span>\n<span class=\"go\">&lt;div&gt;&lt;label for=&quot;id_form-0-name&quot;&gt;Name:&lt;/label&gt;&lt;input id=&quot;id_form-0-name&quot; type=&quot;text&quot; name=&quot;form-0-name&quot; value=&quot;Charles Baudelaire&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-0-id&quot; value=&quot;1&quot; id=&quot;id_form-0-id&quot;&gt;&lt;/div&gt;</span>\n<span class=\"go\">&lt;div&gt;&lt;label for=&quot;id_form-1-name&quot;&gt;Name:&lt;/label&gt;&lt;input id=&quot;id_form-1-name&quot; type=&quot;text&quot; name=&quot;form-1-name&quot; value=&quot;Paul Verlaine&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-1-id&quot; value=&quot;3&quot; id=&quot;id_form-1-id&quot;&gt;&lt;/div&gt;</span>\n<span class=\"go\">&lt;div&gt;&lt;label for=&quot;id_form-2-name&quot;&gt;Name:&lt;/label&gt;&lt;input id=&quot;id_form-2-name&quot; type=&quot;text&quot; name=&quot;form-2-name&quot; value=&quot;Walt Whitman&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-2-id&quot; value=&quot;2&quot; id=&quot;id_form-2-id&quot;&gt;&lt;/div&gt;</span>\n<span class=\"go\">&lt;div&gt;&lt;label for=&quot;id_form-3-name&quot;&gt;Name:&lt;/label&gt;&lt;input id=&quot;id_form-3-name&quot; type=&quot;text&quot; name=&quot;form-3-name&quot; maxlength=&quot;100&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;form-3-id&quot; id=&quot;id_form-3-id&quot;&gt;&lt;/div&gt;</span>\n</code></pre></div>\n<p>Une valeur <code class=\"docutils literal notranslate\">max_num</code> <code class=\"docutils literal notranslate\">None</code> (par défaut) place une limite élevée du nombre de formulaires affichés (1000). En pratique, cela équivaut à aucune limite.</p>\n</section>\n<section id=\"preventing-new-objects-creation\">\n<span id=\"model-formsets-edit-only\"></span><h3>Empêcher la création de nouveaux objets<a class=\"heading-anchor\" href=\"#preventing-new-objects-creation\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Avec le paramètre <code class=\"docutils literal notranslate\">edit_only</code>, il est possible d’empêcher la création de tout nouvel objet :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    Author<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">],</span>\n<span class=\"gp\">... </span>    edit_only<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Ici, le jeu de formulaires ne fera que modifier des instances <code class=\"docutils literal notranslate\">Author</code> existantes. Aucun autre objet ne sera créé ou modifié.</p>\n</section>\n<section id=\"using-a-model-formset-in-a-view\">\n<h3>Utilisation de formulaires groupés de modèle dans une vue<a class=\"heading-anchor\" href=\"#using-a-model-formset-in-a-view\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les formulaires groupés de modèle sont très semblables aux formulaires groupés normaux. Admettons que nous voulions afficher des formulaires groupés pour modifier les instances du modèle <code class=\"docutils literal notranslate\">Author</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\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> modelformset_factory\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Author\n\n\n<span class=\"k\">def</span> <span class=\"nf\">manage_authors</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">])</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s2\">&quot;POST&quot;</span><span class=\"p\">:</span>\n        formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> request<span class=\"o\">.</span>FILES<span class=\"p\">)</span>\n        <span class=\"k\">if</span> formset<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            formset<span class=\"o\">.</span>save<span class=\"p\">()</span>\n            <span class=\"c1\"># do something.</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">()</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s2\">&quot;manage_authors.html&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;formset&quot;</span><span class=\"p\">:</span> formset<span class=\"p\">})</span>\n</code></pre></div>\n<p>Comme vous pouvez le voir, la logique de la vue de formulaires groupés de modèle n’est pas fondamentalement différente de celle de formulaires groupés normaux. La seule différence est que nous appelons <code class=\"docutils literal notranslate\">formset.save()</code> pour enregistrer les données dans la base de données (comme cela a été décrit ci-dessus dans <a class=\"reference internal\" href=\"#saving-objects-in-the-formset\"><span class=\"std std-ref\">Enregistrement des objets des formulaires groupés</span></a>).</p>\n</section>\n<section id=\"overriding-clean-on-a-modelformset\">\n<span id=\"model-formsets-overriding-clean\"></span><h3>Surcharge de <code class=\"docutils literal notranslate\">clean()</code> d’un <code class=\"docutils literal notranslate\">ModelFormSet</code><a class=\"heading-anchor\" href=\"#overriding-clean-on-a-modelformset\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Tout comme pour un <code class=\"docutils literal notranslate\">ModelForm</code>, la méthode <code class=\"docutils literal notranslate\">clean()</code> de <code class=\"docutils literal notranslate\">ModelFormSet</code> valide par défaut qu’aucun des éléments dans les formulaires groupés ne viole les contraintes d’unicité de votre modèle (que ce soit <code class=\"docutils literal notranslate\">unique</code>, <code class=\"docutils literal notranslate\">unique_together</code> ou <code class=\"docutils literal notranslate\">unique_for_date|month|year</code>). Si vous souhaitez surcharger la méthode <code class=\"docutils literal notranslate\">clean()</code> d’un <code class=\"docutils literal notranslate\">ModelFormSet</code> et conserver cette validation, vous devez appeler la méthode <code class=\"docutils literal notranslate\">clean</code> de la classe parente :</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=\"nn\">django.forms</span> <span class=\"kn\">import</span> BaseModelFormSet\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyModelFormSet</span><span class=\"p\">(</span>BaseModelFormSet<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">clean</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>clean<span class=\"p\">()</span>\n        <span class=\"c1\"># example custom validation across forms in the formset</span>\n        <span class=\"k\">for</span> form <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span>forms<span class=\"p\">:</span>\n            <span class=\"c1\"># your custom formset validation</span>\n            <span class=\"o\">...</span>\n</code></pre></div>\n<p>Notez également qu’une fois que vous avez atteint cette étape, les instances de modèles individuelles pour chaque formulaire ont déjà été créées. Il ne suffit donc pas de modifier une valeur dans <code class=\"docutils literal notranslate\">form.cleaned_data</code> pour changer la valeur enregistrée. Si vous souhaitez modifier une valeur dans <code class=\"docutils literal notranslate\">ModelFormSet.clean()</code>, vous devez modifier <code class=\"docutils literal notranslate\">form.instance</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\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> BaseModelFormSet\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyModelFormSet</span><span class=\"p\">(</span>BaseModelFormSet<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">clean</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>clean<span class=\"p\">()</span>\n\n        <span class=\"k\">for</span> form <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span>forms<span class=\"p\">:</span>\n            name <span class=\"o\">=</span> form<span class=\"o\">.</span>cleaned_data<span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">]</span><span class=\"o\">.</span>upper<span class=\"p\">()</span>\n            form<span class=\"o\">.</span>cleaned_data<span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> name\n            <span class=\"c1\"># update the instance value.</span>\n            form<span class=\"o\">.</span>instance<span class=\"o\">.</span>name <span class=\"o\">=</span> name\n</code></pre></div>\n</section>\n<section id=\"using-a-custom-queryset\">\n<h3>Utilisation d’un jeu de requête personnalisé<a class=\"heading-anchor\" href=\"#using-a-custom-queryset\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Comme indiqué précédemment, il est possible de surcharger le jeu de requête utilisé par défaut par les formulaires groupés de modèle :</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=\"nn\">django.forms</span> <span class=\"kn\">import</span> modelformset_factory\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Author\n\n\n<span class=\"k\">def</span> <span class=\"nf\">manage_authors</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    AuthorFormSet <span class=\"o\">=</span> modelformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;title&quot;</span><span class=\"p\">])</span>\n    queryset <span class=\"o\">=</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>name__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;O&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s2\">&quot;POST&quot;</span><span class=\"p\">:</span>\n        formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">(</span>\n            request<span class=\"o\">.</span>POST<span class=\"p\">,</span>\n            request<span class=\"o\">.</span>FILES<span class=\"p\">,</span>\n            queryset<span class=\"o\">=</span>queryset<span class=\"p\">,</span>\n        <span class=\"p\">)</span>\n        <span class=\"k\">if</span> formset<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            formset<span class=\"o\">.</span>save<span class=\"p\">()</span>\n            <span class=\"c1\"># Do something.</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        formset <span class=\"o\">=</span> AuthorFormSet<span class=\"p\">(</span>queryset<span class=\"o\">=</span>queryset<span class=\"p\">)</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s2\">&quot;manage_authors.html&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;formset&quot;</span><span class=\"p\">:</span> formset<span class=\"p\">})</span>\n</code></pre></div>\n<p>Notez que nous transmettons le paramètre <code class=\"docutils literal notranslate\">queryset</code> à la fois aux requêtes <code class=\"docutils literal notranslate\">POST</code> et <code class=\"docutils literal notranslate\">GET</code> dans cet exemple.</p>\n</section>\n<section id=\"using-the-formset-in-the-template\">\n<h3>Utilisation des formulaires groupés dans un gabarit<a class=\"heading-anchor\" href=\"#using-the-formset-in-the-template\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il y a trois façons d’afficher des formulaires groupés dans un gabarit Django.</p>\n<p>Premièrement, vous pouvez déléguer aux formulaires groupés l’essentiel du travail :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{{</span> <span class=\"nv\">formset</span> <span class=\"cp\">}}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Deuxièmement, vous pouvez afficher les formulaires groupés manuellement, mais laisser le soin à chaque formulaire de s’afficher lui-même :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{{</span> <span class=\"nv\">formset.management_form</span> <span class=\"cp\">}}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">form</span> <span class=\"k\">in</span> <span class=\"nv\">formset</span> <span class=\"cp\">%}</span>\n        <span class=\"cp\">{{</span> <span class=\"nv\">form</span> <span class=\"cp\">}}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Lorsque vous vous occupez vous-même d’afficher les différents formulaires, prenez soin d’inclure également le formulaire de gestion comme le montre l’exemple ci-dessus. Voir la <a class=\"reference internal\" href=\"/fr/6.0/topics/forms/formsets/#understanding-the-managementform\"><span class=\"std std-ref\">documentation du formulaire de gestion</span></a>.</p>\n<p>Troisièmement, vous pouvez afficher manuellement chaque champ :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{{</span> <span class=\"nv\">formset.management_form</span> <span class=\"cp\">}}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">form</span> <span class=\"k\">in</span> <span class=\"nv\">formset</span> <span class=\"cp\">%}</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">field</span> <span class=\"k\">in</span> <span class=\"nv\">form</span> <span class=\"cp\">%}</span>\n            <span class=\"cp\">{{</span> <span class=\"nv\">field.label_tag</span> <span class=\"cp\">}}</span> <span class=\"cp\">{{</span> <span class=\"nv\">field</span> <span class=\"cp\">}}</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Si vous optez pour cette troisième méthode et que vous ne bouclez pas sur les champs avec un <code class=\"docutils literal notranslate\">{% for %}</code>, vous devez aussi inclure le champ de clé primaire. Par exemple, si vous affichez les champs <code class=\"docutils literal notranslate\">name</code> et <code class=\"docutils literal notranslate\">age</code> d’un modèle :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{{</span> <span class=\"nv\">formset.management_form</span> <span class=\"cp\">}}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">form</span> <span class=\"k\">in</span> <span class=\"nv\">formset</span> <span class=\"cp\">%}</span>\n        <span class=\"cp\">{{</span> <span class=\"nv\">form.id</span> <span class=\"cp\">}}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n            <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">form.name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n            <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">form.age</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n        <span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Voyez comment nous devons explicitement afficher <code class=\"docutils literal notranslate\">{{ form.id }}</code>. Ceci pour s’assurer du bon fonctionnement des formulaires groupés de modèle, dans le cas de l’envoi <code class=\"docutils literal notranslate\">POST</code> (cet exemple suppose que la clé primaire s’appelle <code class=\"docutils literal notranslate\">id</code>. Si vous avez explicitement nommé la clé primaire su modèle autrement que <code class=\"docutils literal notranslate\">id</code>, prenez soin de l’afficher).</p>\n</section>\n</section>\n<section id=\"inline-formsets\">\n<span id=\"id4\"></span><h2>Sous-formulaires groupés<a class=\"heading-anchor\" href=\"#inline-formsets\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.forms.models.BaseInlineFormSet\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-prename descclassname\">models.</span><span class=\"sig-name descname\">BaseInlineFormSet</span><a class=\"heading-anchor\" href=\"#django.forms.models.BaseInlineFormSet\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Les sous-formulaires groupés sont une petite couche d’abstraction au-dessus des formulaires groupés de modèle. Ils simplifient la situation où l’on manipule des objets liés au travers d’une clé étrangère. Supposons que l’on dispose de ces deux modèles :</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=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Author</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Book</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    author <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>Author<span class=\"p\">,</span> on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">)</span>\n    title <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Si vous voulez créer des formulaires groupés permettant de modifier les livres appartenant à un auteur particulier, vous pourriez faire ainsi :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> inlineformset_factory\n<span class=\"gp\">&gt;&gt;&gt; </span>BookFormSet <span class=\"o\">=</span> inlineformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> Book<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;title&quot;</span><span class=\"p\">])</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>author <span class=\"o\">=</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s2\">&quot;Mike Royko&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>formset <span class=\"o\">=</span> BookFormSet<span class=\"p\">(</span>instance<span class=\"o\">=</span>author<span class=\"p\">)</span>\n</code></pre></div>\n<p>Le <a class=\"reference internal\" href=\"/fr/6.0/topics/forms/formsets/#formset-prefix\"><span class=\"std std-ref\">préfixe</span></a> de <code class=\"docutils literal notranslate\">BookFormSet</code> est <code class=\"docutils literal notranslate\">'book_set'</code> (<code class=\"docutils literal notranslate\">&lt;nom_modèle&gt;_set</code> ). Si la clé étrangère de <code class=\"docutils literal notranslate\">Book</code> vers <code class=\"docutils literal notranslate\">Author</code> possède l’attribut <a class=\"reference internal\" href=\"/fr/6.0/ref/models/fields/#django.db.models.ForeignKey.related_name\" title=\"django.db.models.ForeignKey.related_name\"><code class=\"xref py py-attr docutils literal notranslate\">related_name</code></a>, c’est ce dernier qui est utilisé.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p><a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.inlineformset_factory\" title=\"django.forms.models.inlineformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">inlineformset_factory()</code></a> utilise <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.modelformset_factory\" title=\"django.forms.models.modelformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">modelformset_factory()</code></a> et définit <code class=\"docutils literal notranslate\">can_delete=True</code>.</p>\n</aside>\n<aside class=\"admonition admonition-seealso\" role=\"note\">\n<p class=\"admonition-title\">Voir aussi</p>\n<p><a class=\"reference internal\" href=\"/fr/6.0/topics/forms/formsets/#manually-rendered-can-delete-and-can-order\"><span class=\"std std-ref\">can_delete et can_order affichés manuellement</span></a>.</p>\n</aside>\n<section id=\"overriding-methods-on-an-inlineformset\">\n<h3>Surcharge des méthodes d’un <code class=\"docutils literal notranslate\">InlineFormSet</code><a class=\"heading-anchor\" href=\"#overriding-methods-on-an-inlineformset\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque vous surchargez des méthodes de sous-formulaires groupés (<code class=\"docutils literal notranslate\">InlineFormSet</code>), il est préférable d’hériter de <a class=\"reference internal\" href=\"#django.forms.models.BaseInlineFormSet\" title=\"django.forms.models.BaseInlineFormSet\"><code class=\"xref py py-class docutils literal notranslate\">BaseInlineFormSet</code></a> plutôt que de <a class=\"reference internal\" href=\"#django.forms.models.BaseModelFormSet\" title=\"django.forms.models.BaseModelFormSet\"><code class=\"xref py py-class docutils literal notranslate\">BaseModelFormSet</code></a>.</p>\n<p>Par exemple, si vous souhaitez surcharger <code class=\"docutils literal notranslate\">clean()</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\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> BaseInlineFormSet\n\n\n<span class=\"k\">class</span> <span class=\"nc\">CustomInlineFormSet</span><span class=\"p\">(</span>BaseInlineFormSet<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">clean</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>clean<span class=\"p\">()</span>\n        <span class=\"c1\"># example custom validation across forms in the formset</span>\n        <span class=\"k\">for</span> form <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span>forms<span class=\"p\">:</span>\n            <span class=\"c1\"># your custom formset validation</span>\n            <span class=\"o\">...</span>\n</code></pre></div>\n<p>Voir aussi <a class=\"reference internal\" href=\"#model-formsets-overriding-clean\"><span class=\"std std-ref\">Surcharge de clean() d’un ModelFormSet</span></a>.</p>\n<p>Puis, au moment de créer les sous-formulaires groupés, passez le paramètre facultatif <code class=\"docutils literal notranslate\">formset</code>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.forms</span> <span class=\"kn\">import</span> inlineformset_factory\n<span class=\"gp\">&gt;&gt;&gt; </span>BookFormSet <span class=\"o\">=</span> inlineformset_factory<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    Author<span class=\"p\">,</span> Book<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;title&quot;</span><span class=\"p\">],</span> formset<span class=\"o\">=</span>CustomInlineFormSet\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>author <span class=\"o\">=</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s2\">&quot;Mike Royko&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>formset <span class=\"o\">=</span> BookFormSet<span class=\"p\">(</span>instance<span class=\"o\">=</span>author<span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"more-than-one-foreign-key-to-the-same-model\">\n<h3>Plus d’une clé étrangère vers le même modèle<a class=\"heading-anchor\" href=\"#more-than-one-foreign-key-to-the-same-model\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si votre modèle contient plus d’une clé étrangère vers le même modèle, vous devrez résoudre l’ambiguïté manuellement en utilisant <code class=\"docutils literal notranslate\">fk_name</code>. Par exemple, considérez le modèle suivant :</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=\"nc\">Friendship</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    from_friend <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>\n        Friend<span class=\"p\">,</span>\n        on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">,</span>\n        related_name<span class=\"o\">=</span><span class=\"s2\">&quot;from_friends&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n    to_friend <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>\n        Friend<span class=\"p\">,</span>\n        on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">,</span>\n        related_name<span class=\"o\">=</span><span class=\"s2\">&quot;friends&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n    length_in_months <span class=\"o\">=</span> models<span class=\"o\">.</span>IntegerField<span class=\"p\">()</span>\n</code></pre></div>\n<p>Pour résoudre cela, vous pouvez définir <code class=\"docutils literal notranslate\">fk_name</code> dans <a class=\"reference internal\" href=\"/fr/6.0/ref/forms/models/#django.forms.models.inlineformset_factory\" title=\"django.forms.models.inlineformset_factory\"><code class=\"xref py py-func docutils literal notranslate\">inlineformset_factory()</code></a>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>FriendshipFormSet <span class=\"o\">=</span> inlineformset_factory<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    Friend<span class=\"p\">,</span> Friendship<span class=\"p\">,</span> fk_name<span class=\"o\">=</span><span class=\"s2\">&quot;from_friend&quot;</span><span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;to_friend&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;length_in_months&quot;</span><span class=\"p\">]</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"using-an-inline-formset-in-a-view\">\n<h3>Utilisation de sous-formulaires groupés dans une vue<a class=\"heading-anchor\" href=\"#using-an-inline-formset-in-a-view\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il peut être nécessaire de définir une vue permettant à un utilisateur de modifier les objets liés d’un modèle. Voici comment on peut le faire :</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=\"nf\">manage_books</span><span class=\"p\">(</span>request<span class=\"p\">,</span> author_id<span class=\"p\">):</span>\n    author <span class=\"o\">=</span> Author<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>pk<span class=\"o\">=</span>author_id<span class=\"p\">)</span>\n    BookInlineFormSet <span class=\"o\">=</span> inlineformset_factory<span class=\"p\">(</span>Author<span class=\"p\">,</span> Book<span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;title&quot;</span><span class=\"p\">])</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s2\">&quot;POST&quot;</span><span class=\"p\">:</span>\n        formset <span class=\"o\">=</span> BookInlineFormSet<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> request<span class=\"o\">.</span>FILES<span class=\"p\">,</span> instance<span class=\"o\">=</span>author<span class=\"p\">)</span>\n        <span class=\"k\">if</span> formset<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            formset<span class=\"o\">.</span>save<span class=\"p\">()</span>\n            <span class=\"c1\"># Do something. Should generally end with a redirect. For example:</span>\n            <span class=\"k\">return</span> HttpResponseRedirect<span class=\"p\">(</span>author<span class=\"o\">.</span>get_absolute_url<span class=\"p\">())</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        formset <span class=\"o\">=</span> BookInlineFormSet<span class=\"p\">(</span>instance<span class=\"o\">=</span>author<span class=\"p\">)</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s2\">&quot;manage_books.html&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;formset&quot;</span><span class=\"p\">:</span> formset<span class=\"p\">})</span>\n</code></pre></div>\n<p>Notez comment nous définissons le paramètre <code class=\"docutils literal notranslate\">instance</code> aussi bien dans le cas <code class=\"docutils literal notranslate\">POST</code> que le cas <code class=\"docutils literal notranslate\">GET</code>.</p>\n</section>\n<section id=\"specifying-widgets-to-use-in-the-inline-form\">\n<h3>Indication des composants à utiliser dans le sous-formulaire<a class=\"heading-anchor\" href=\"#specifying-widgets-to-use-in-the-inline-form\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\">inlineformset_factory</code> utilise <code class=\"docutils literal notranslate\">modelformset_factory</code> et transmet la plupart de ses paramètres à <code class=\"docutils literal notranslate\">modelformset_factory</code>. Cela signifie que vous pouvez utiliser le paramètre <code class=\"docutils literal notranslate\">widgets</code> tout comme vous le feriez pour <code class=\"docutils literal notranslate\">modelformset_factory</code>. Voir <a class=\"reference internal\" href=\"#specifying-widgets-to-use-in-the-form-with-widgets\">Indication des composants de formulaire à utiliser avec widgets</a> ci-dessus.</p>\n</section>\n</section>","rootId":"creating-forms-from-models","toc":[{"title":"ModelForm","anchor":"modelform","children":[{"title":"Types de champs","anchor":"field-types","children":[]},{"title":"Un exemple complet","anchor":"a-full-example","children":[]},{"title":"Validation d’un ModelForm","anchor":"validation-on-a-modelform","children":[{"title":"Surcharge de la méthode clean()","anchor":"overriding-the-clean-method","children":[]},{"title":"Interactions avec la validation des modèles","anchor":"interaction-with-model-validation","children":[]},{"title":"Considérations sur les messages d’erreur des modèles","anchor":"considerations-regarding-model-s-error-messages","children":[]}]},{"title":"La méthode save()","anchor":"the-save-method","children":[]},{"title":"Sélection des champs à utiliser","anchor":"selecting-the-fields-to-use","children":[]},{"title":"Surcharge des champs par défaut","anchor":"overriding-the-default-fields","children":[]},{"title":"Activation de la régionalisation des champs","anchor":"enabling-localization-of-fields","children":[]},{"title":"Héritage de formulaire","anchor":"form-inheritance","children":[]},{"title":"Indication de valeurs initiales","anchor":"providing-initial-values","children":[]},{"title":"Fonction de fabrique de ModelForm","anchor":"modelform-factory-function","children":[]}]},{"title":"Formulaires groupés de modèles","anchor":"model-formsets","children":[{"title":"Modification du jeu de requête","anchor":"changing-the-queryset","children":[]},{"title":"Modification du formulaire","anchor":"changing-the-form","children":[]},{"title":"Indication des composants de formulaire à utiliser avec widgets","anchor":"specifying-widgets-to-use-in-the-form-with-widgets","children":[]},{"title":"Activation de la régionalisation des champs avec localized_fields","anchor":"enabling-localization-for-fields-with-localized-fields","children":[]},{"title":"Indication de valeurs initiales","anchor":"id2","children":[]},{"title":"Enregistrement des objets des formulaires groupés","anchor":"saving-objects-in-the-formset","children":[]},{"title":"Restriction du nombre d’objets modifiables","anchor":"limiting-the-number-of-editable-objects","children":[]},{"title":"Empêcher la création de nouveaux objets","anchor":"preventing-new-objects-creation","children":[]},{"title":"Utilisation de formulaires groupés de modèle dans une vue","anchor":"using-a-model-formset-in-a-view","children":[]},{"title":"Surcharge de clean() d’un ModelFormSet","anchor":"overriding-clean-on-a-modelformset","children":[]},{"title":"Utilisation d’un jeu de requête personnalisé","anchor":"using-a-custom-queryset","children":[]},{"title":"Utilisation des formulaires groupés dans un gabarit","anchor":"using-the-formset-in-the-template","children":[]}]},{"title":"Sous-formulaires groupés","anchor":"inline-formsets","children":[{"title":"Surcharge des méthodes d’un InlineFormSet","anchor":"overriding-methods-on-an-inlineformset","children":[]},{"title":"Plus d’une clé étrangère vers le même modèle","anchor":"more-than-one-foreign-key-to-the-same-model","children":[]},{"title":"Utilisation de sous-formulaires groupés dans une vue","anchor":"using-an-inline-formset-in-a-view","children":[]},{"title":"Indication des composants à utiliser dans le sous-formulaire","anchor":"specifying-widgets-to-use-in-the-inline-form","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/6.0/topics/"},{"docname":"topics/forms/index","title":"Utilisation des formulaires","url":"/fr/6.0/topics/forms/"}],"prev":{"docname":"topics/forms/formsets","title":"Formulaires groupés","url":"/fr/6.0/topics/forms/formsets/"},"next":{"docname":"topics/forms/media","title":"Fichiers annexes de formulaire (classe Media)","url":"/fr/6.0/topics/forms/media/"},"formats":{"html":"/fr/6.0/topics/forms/modelforms/","markdown":"/fr/6.0/topics/forms/modelforms.md","json":"/fr/6.0/topics/forms/modelforms.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/topics/forms/modelforms.txt","official":"https://docs.djangoproject.com/fr/6.0/topics/forms/modelforms/","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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}