# Documentation Django 6.0.7

# Utilisation des formulaires

À propos de ce document

Ce document présente une introduction aux bases des formulaires web et à la manière dont ils sont traités par Django. Pour plus de détails sur des aspects spécifiques de l’API des formulaires, consultez L’API des formulaires, Champs de formulaires, et La validation de formulaires et de champs.

À moins que vous n’ayez l’intention de construire des sites Web et des applications qui ne font rien d’autre que de publier du contenu, et n’acceptant aucune saisie de la part de ses visiteurs, vous allez avoir besoin de comprendre et d’utiliser des formulaires.

Django fournit un certain nombre d’outils et de bibliothèques pour vous aider à créer des formulaires de saisie pour les visiteurs du site, puis pour aider à traiter et à répondre à ces saisies.

## Formulaires HTML

En HTML, un formulaire est un ensemble d’éléments à l’intérieur des balises `<form>...</form>` qui permettent à un visiteur d’effectuer des actions comme saisir du texte, sélectionner des options, manipuler des objets ou des contrôles, et ainsi de suite, puis d’envoyer ces informations au serveur.

Certains de ces éléments d’interface de formulaires - boîtes de saisie de texte ou cases à cocher - sont intégrés à HTML. D’autres éléments sont beaucoup plus complexes ; une interface qui affiche un sélecteur de date ou qui permet de déplacer un curseur ou de contrôler un autre élément graphique utilise généralement du code JavaScript et CSS, ainsi que des éléments `<input>` de formulaires HTML pour produire ce genre d’effets.

En plus de ses éléments `<input>`, un formulaire doit préciser deux choses :

- où : l’URL vers laquelle les données correspondant à la saisie de l’utilisateur doivent être renvoyées

- comment : la méthode HTTP utilisée pour renvoyer les données

Par exemple, le formulaire de connexion pour l’administration de Django contient plusieurs éléments `<input>`: un de `type="text"` pour le nom d’utilisateur, un de `type="password"` pour le mot de passe, et un de `type="submit"` pour le bouton « Connexion ». Il contient également des champs de texte cachés que l’utilisateur ne voit pas, mais que Django utilise pour déterminer ce qu’il faut faire après la connexion.

Il indique également au navigateur que les données du formulaire doivent être envoyées à l’URL spécifiée dans l’attribut `action` de la balise `<form>` (`/admin/`) et qu’elles doivent être envoyées en utilisant le mécanisme HTTP spécifié par l’attribut `method` (`post`).

Lorsque le bouton `<input type="submit" value="Connexion">` est déclenché, les données sont renvoyées à `/admin/`.

### `GET` et `POST`

`GET` et `POST` sont les seules méthodes HTTP à utiliser dans les formulaires.

Le formulaire de connexion de Django est renvoyé en utilisant la méthode `POST`, par laquelle le navigateur regroupe les données du formulaire, les encode pour la transmission, les envoie au serveur, puis reçoit la réponse en retour.

`GET`, en revanche, regroupe les données fournies dans une chaîne et l’utilise pour composer une URL. L’URL contient l’adresse à laquelle les données doivent être envoyées, ainsi que les clés et les valeurs fournies. Vous pouvez en voir un exemple si vous effectuez une recherche dans la documentation de Django, car cela va produire une URL de la forme `https://docs.djangoproject.com/search/?q=forms&release=1`.

`GET` et `POST` sont généralement utilisées à des fins différentes.

Toute requête pouvant être utilisée pour modifier l’état du système, par exemple une requête qui applique des changements en base de données, devrait utiliser `POST`. `GET` ne devrait être employée que pour des requêtes qui n’affectent pas l’état du système.

`GET` ne conviendrait pas non plus pour un formulaire de changement de mot de passe, car le mot de passe apparaîtrait en clair dans l’URL ainsi que dans l’historique du navigateur et les journaux du serveur. Elle ne conviendrait pas non plus pour des données volumineuses ou pour des données binaires telles que pour une image. Une application Web utilisant des requêtes `GET` pour des formulaires administratifs ne serait pas sécurisée : il est facile pour un attaquant de simuler une requête de formulaire pour obtenir l’accès à des parties sensibles du système. Les requêtes `POST` accompagnées par d’autres protections comme la protection CSRF de Django offrent un bien meilleur contrôle sur les accès.

D’autre part, `GET` convient pour des interfaces comme un formulaire de recherche Web, car les URL qui représentent une requête `GET` peuvent être facilement conservées dans un signet, partagées ou ré-envoyées.

## Le rôle de Django dans les formulaires

La gestion des formulaires est une affaire complexe. Considérez l’application d’administration de Django où de nombreuses données de différents types doivent être préparées pour être affichées dans un formulaire, produites en HTML, éditées par une interface conviviale, renvoyées vers le serveur, validées et nettoyées, et finalement enregistrées ou transmises pour traitement ultérieur.

La fonctionnalité des formulaires de Django peut simplifier et automatiser de larges portions de ce travail et peut aussi le faire de manière plus sécurisée que la plupart des programmeurs ne pourraient le faire en écrivant leur propre code.

Django gère trois parties distinctes du travail induit par les formulaires :

- préparation et restructuration des données en vue de leur présentation

- création des formulaires HTML pour les données

- réception et traitement des formulaires et des données envoyés par le client

Il est possible d’écrire du code qui fait tout cela manuellement, mais Django peut s’en charger à votre place.

## Les formulaires dans Django

Nous avons brièvement décrit les formulaires HTML, mais un objet HTML `<form>` n’est qu’un élément de la machinerie nécessaire.

Dans le contexte d’une application Web, « formulaire » peut se référer à cette balise HTML `<form>`, à la classe `Form` de Django qui la produit, aux données structurées renvoyées lorsque le formulaire est soumis, ou encore au fonctionnement de bout en bout de ces différentes parties.

### La classe `Form` de Django

La classe `Form` de Django se situe au cœur de ce système de composants. De la même façon qu’un modèle Django décrit la structure logique d’un objet, son comportement et la manière dont ses parties nous sont présentées, une classe `Form` décrit un formulaire et détermine son fonctionnement et son apparence.

De la même façon que les champs d’une classe de modèle correspondent à des champs de base de données, les champs d’une classe de formulaire correspondent aux éléments `<input>` d’un formulaire HTML (un `ModelForm` fait correspondre les champs d’une classe de modèle à des éléments `<input>` d’un formulaire HTML via un formulaire `Form`; cela constitue la base de l’interface d’administration de Django).

Les champs d’un formulaire sont eux-mêmes des classes ; elles gèrent les données de formulaire et s’occupent de la validation lorsque des données de formulaires sont reçues. Un champ `DateField` et un champ `FileField` gèrent des types de données très différents et doivent procéder à des actions différentes.

Un champ de formulaire est présenté dans une interface de navigateur sous forme de « composant » HTML, un élément d’interface utilisateur. Chaque type de champ contient une classe Widget appropriée par défaut, mais celles-ci peuvent être remplacées au besoin.

### Instanciation, traitement et rendu des formulaires

Lors du rendu d’un objet Django pour son affichage, il s’agit généralement de :

1. obtenir l’élément dans la vue (le récupérer à partir de la base de données, par exemple)

2. le transmettre au contexte de gabarit

3. le transformer en balisage HTML en utilisant des variables de gabarit

L’affichage d’un formulaire dans un gabarit suit à peu près le même processus que pour tout autre type d’objet, mais il y a tout de même certaines différences notables.

Dans le cas d’une instance de modèle ne contenant aucune donnée, il n’y aura pas beaucoup de sens d’en faire quoi que ce soit dans un gabarit. En revanche, il est totalement raisonnable de vouloir afficher un formulaire vierge, c’est ce qu’il faut faire lorsqu’on veut que quelqu’un le remplisse.

Ainsi, lorsque nous manipulons une instance de modèle dans une vue, nous la récupérons typiquement à partir de la base de données. Lorsque nous manipulons un formulaire, nous en créons typiquement une instance dans la vue.

Lors de la création d’une instance de formulaire, on peut choisir de le laisser vide ou de le pré-remplir, par exemple avec :

- des données provenant d’une instance de modèle enregistrée (comme dans le cas des formulaires d’administration pour l’édition)

- des données que nous avons obtenues à partir d’autres sources

- des données reçues d’un envoi de formulaire HTML

Le dernier de ces cas est le plus intéressant, car c’est ce qui permet aux utilisateurs de ne pas seulement lire un site Web, mais aussi de renvoyer des informations aux sites Web.

## Construction d’un formulaire

### Le travail à effectuer

Supposons que vous vouliez créer un formulaire simple sur votre site dans le but d’obtenir le nom de l’utilisateur. Voici ce qu’il faudrait obtenir dans le navigateur :

    <form action="/your-name/" method="post">
        <label for="your_name">Your name: </label>
        <input id="your_name" type="text" name="your_name" value="{{ current_name }}">
        <input type="submit" value="OK">
    </form>

Le navigateur saura alors qu’il doit renvoyer les données du formulaire vers l’URL `/your-name/`, en utilisant la méthode `POST`. Il affichera un champ de texte libellé « Your name: » et un bouton intitulé « OK ». Si le contexte de gabarit contient une variable `current_name`, celle-ci sera utilisée pour pré-remplir le champ `your_name`.

Il faudra une vue qui produit le gabarit contenant le formulaire HTML et qui puisse fournir le champ `current_name` si nécessaire.

Lorsque le formulaire aura été envoyé, la requête `POST` envoyée au serveur contiendra les données du formulaire.

Mais il sera également nécessaire d’avoir une vue répondant à l’URL `/your-name/` qui se chargera de trouver les paires clé-valeur dans la requête, puis de les traiter.

Il s’agit d’un formulaire très simple. En pratique, un formulaire peut contenir des dizaines ou centaines de champs, dont beaucoup peuvent être pré-remplis, et il est possible que l’utilisateur doive passer par plusieurs cycles d’envoi/édition avant que l’opération globale ne soit terminée.

On peut attendre du navigateur qu’il s’occupe d’une partie de la validation, même avant que le formulaire ne soit envoyé. Peut-être que certains champs seront bien plus complexes, permettant par exemple de choisir des dates dans un calendrier.

Compte tenu de tout ceci, il est bien plus avantageux que Django se charge lui-même de la plupart du travail.

### Construction d’un formulaire dans Django

#### La classe `Form`

Nous savons déjà à quoi notre formulaire HTML doit ressembler. Notre point de départ dans Django est le suivant :

`forms.py`

    from django import forms

    class NameForm(forms.Form):
        your_name = forms.CharField(label="Your name", max_length=100)

Cela définit une classe `Form` comportant un seul champ (`your_name`). Nous avons attribué une étiquette conviviale à ce champ ; celle-ci apparaîtra dans la balise `<label>` au moment de l’affichage (bien que dans ce cas, le contenu indiqué dans `label` est en réalité identique à celui qui aurait été généré automatiquement si nous n’avions rien fait).

La longueur maximale du champ est définie par `max_length`. Cela fait deux choses : la balise HTML `<input>` reçoit l’attribut `maxlength="100"` (afin que le navigateur empêche lui-même la saisie d’un plus grand nombre de caractères), et ultérieurement lorsque Django reçoit en retour les données de formulaire, il valide que les données respectent cette longueur.

Une instance de `Form` possède une méthode `is_valid()` qui procède aux routines de validation pour tous ses champs. Lorsque la méthode est appelée et que tous les champs contiennent des données valables, celle-ci :

- renvoie `True`;

- insère les données du formulaire dans l’attribut `cleaned_data`.

Le formulaire complet, lorsqu’il est affiché pour la première fois, ressemble à ceci :

    <label for="your_name">Your name: </label>
    <input id="your_name" type="text" name="your_name" maxlength="100" required>

Notez qu’il n’inclut pas les balises `<form>` ni de bouton d’envoi. Ces éléments doivent être ajoutés par celui qui rédige le gabarit.

#### La vue

Les données de formulaire renvoyés à un site Web Django sont traitées par une vue, en principe la même qui a servi à produire le formulaire. Cela permet de réutiliser une partie de la même logique.

Pour traiter le formulaire, nous devons en créer une instance dans la vue à destination de l’URL à laquelle il doit apparaître :

`views.py`

    from django.http import HttpResponseRedirect
    from django.shortcuts import render

    from .forms import NameForm

    def get_name(request):
        # if this is a POST request we need to process the form data
        if request.method == "POST":
            # create a form instance and populate it with data from the request:
            form = NameForm(request.POST)
            # check whether it's valid:
            if form.is_valid():
                # process the data in form.cleaned_data as required
                # ...
                # redirect to a new URL:
                return HttpResponseRedirect("/thanks/")

        # if a GET (or any other method) we'll create a blank form
        else:
            form = NameForm()

        return render(request, "name.html", {"form": form})

Si nous arrivons dans cette vue avec une requête `GET`, la vue crée une instance de formulaire vierge et la place dans le contexte de gabarit en vue de son affichage. C’est à quoi l’on peut s’attendre lors du premier accès à l’URL en question.

Si le formulaire est envoyé par une requête `POST`, la vue crée également une instance de formulaire et la complète avec les données reçues à partir de la requête : `form = NameForm(request.POST)`. C’est ce qu’on appelle « lier les données au formulaire » (il s’agit maintenant d’un formulaire lié, « bound » en anglais).

La méthode `is_valid()` est appelée ; si elle ne renvoie pas `True`, on se retrouve au stade du gabarit contenant le formulaire. Mais cette fois, le formulaire n’est plus vierge (non lié ou unbound) ce qui fait que le formulaire HTML sera rempli avec les données saisies précédemment, données qui peuvent être modifiées et corrigées selon les besoins.

Si `is_valid()` renvoie `True`, toutes les données validées du formulaire sont alors accessibles dans l’attribut `cleaned_data`. Ces données peuvent être utilisées pour mettre à jour la base de données ou effectuer d’autres opérations avant de renvoyer au navigateur une redirection HTTP lui indiquant l’URL à recharger.

#### Le gabarit

Il n’y a pas grand chose à faire dans le gabarit `name.html`:

    <form action="/your-name/" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit">
    </form>

Tous les champs de formulaire et leurs attributs seront convertis en balises HTML à partir de `{{ form }}` par le langage de gabarit de Django.

Formulaires et protection contre le « Cross site request forgery » (CSRF)

Django est livré avec une protection simple d’emploi contre les attaques de type Cross Site Request Forgeries. Lors de l’envoi d’un formulaire par la méthode `POST` et la protection CSRF active, vous devez utiliser la balise de gabarit `csrf_token` comme dans l’exemple précédent. Cependant, comme la protection CSRF n’est pas directement liée aux formulaires dans les gabarits, cette balise est omise dans les exemples suivants de ce document.

Types de composants HTML5 et validation par le navigateur

Si un formulaire contient un champ de type `URLField`, `EmailField` ou tout type de champ nombre entier, Django fait appel aux composants HTML5 (input) de type `url`, `email` et `number`. Par défaut, les navigateurs appliquent souvent leur propre validation de ces champs, qui peut être plus stricte que celle de Django. Si vous voulez échapper à cette validation, ajoutez l’attribut `novalidate` sur la balise `form` ou définissez un autre composant de formulaire pour le champ, comme par exemple `TextInput`.

Nous possédons maintenant un formulaire Web fonctionnel, défini par une instance `Form` de Django, traité par une vue et affiché sous forme de balise HTML `<form>`.

C’est tout ce dont vous avez besoin pour commencer, mais l’infrastructure des formulaires a beaucoup plus à vous offrir. À partir du moment où vous comprenez les bases du processus décrit ci-dessus, il est bon de connaître les autres fonctionnalités mises à disposition par le système des formulaires et d’en savoir un peu plus au sujet de la machinerie sous-jacente.

## Plus de détails sur les classes `Form` de Django

Toutes les classes de formulaires sont créées comme sous-classes de `django.forms.Form` ou de `django.forms.ModelForm`. `ModelForm` peut être considéré comme une sous-classe de `Form`. `Form` et `ModelForm` héritent effectivement de comportements communs provenant de la classe (privée) `BaseForm`, mais ce détail d’implémentation est rarement significatif.

Modèles et formulaires

En fait, si un formulaire est destiné à ajouter ou modifier directement un modèle Django, un formulaire ModelForm peut vous économiser beaucoup de temps, d’effort et de code, car il s’occupe de construire un formulaire avec tous les champs et attributs appropriés à partir d’une classe `Model`.

### Instances de formulaires liées et non liées

La distinction entre Formulaires liés et non liés est importante :

- Un formulaire non renseigné n’a aucune donnée associée. Lorsqu’il est présenté à l’utilisateur, il sera vide ou ne contiendra que des valeurs par défaut.

- Un formulaire renseigné contient des données envoyées et il est donc possible de lui demander si ces données sont valides. Si un formulaire renseigné non valide est affiché, il peut contenir des messages d’erreur intégrés indiquant à l’utilisateur quelles sont les données à corriger.

L’attribut `is_bound` d’un formulaire indique si des données ont été liées au formulaire ou pas.

### Plus de détails sur les champs

Voici un formulaire un peu plus utile que notre exemple minimal ci-dessus, que nous pourrions utiliser pour implémenter une fonctionnalité « Contactez-moi » sur un site Web personnel :

`forms.py`

    from django import forms

    class ContactForm(forms.Form):
        subject = forms.CharField(max_length=100)
        message = forms.CharField(widget=forms.Textarea)
        contact_email = forms.EmailField()
        urgent = forms.BooleanField(required=False)

Our earlier form used a single field, `your_name`, a `CharField`. In this case, our form has four fields: `subject`, `message`, `contact_email` and `urgent`. `CharField`, `EmailField` and `BooleanField` are just three of the available field types; a full list can be found in Champs de formulaires.

#### Composants de formulaires (« widgets »)

À chaque champ de formulaire correspond une classe Widget, qui elle-même se réfère à un composant de formulaire HTML comme par exemple `<input type="text">`.

Dans la plupart des cas, le composant par défaut du champ convient bien. Par exemple, le composant par défaut du champ `CharField` est `TextInput`, qui produit une balise `<input type="text">` en HTML. Si au contraire vous aviez souhaité une balise `<textarea>`, il aurait fallu définir le composant approprié lors de la définition du champ de formulaire, comme nous l’avons fait pour le champ `message`.

#### Données de champ

Quelles que soient les données envoyées avec un formulaire, au moment où elles ont été validées avec succès suite à l’appel de `is_valid()` (et que `is_valid()` a renvoyé `True`), les données de formulaire validées se trouvent dans le dictionnaire `form.cleaned_data`. Ces données auront été gracieusement converties en types Python pour vous.

Note

À ce stade, vous pouvez toujours accéder directement aux données non validées dans `request.POST`, mais les données validées sont plus adéquates.

In the contact form example above, `urgent` will be a boolean value. Likewise, fields such as `IntegerField` and `FloatField` convert values to a Python `int` and `float` respectively.

Voici comment les données de formulaire pourraient être traitées dans la vue qui gère ce formulaire :

`views.py`

    from django.core.mail import EmailMessage

    if form.is_valid():
        subject = form.cleaned_data["subject"]
        message = form.cleaned_data["message"]
        contact_email = form.cleaned_data["contact_email"]
        urgent = form.cleaned_data["urgent"]

        body = (
            "Submitted through the contact form.\n"
            f"Contact email (unverified): {contact_email}\n"
            f"Marked urgent: {'yes' if urgent else 'no'}\n"
            f"Message:\n{message}"
        )

        # Send the message, directing replies to the contact_email.
        EmailMessage(
            subject=f"[contact form] {subject}",
            body=body,
            from_email="contact-form@example.com",
            to=["info@example.com"],
            headers={"Importance": "high"} if urgent else None,
            reply_to=[contact_email],
        ).send()

        return HttpResponseRedirect("/thanks/")

Astuce

Pour en savoir plus sur l’envoi de courriels à partir de Django, consultez Envoi de messages électroniques.

Certains types de champ ont besoin de traitement supplémentaire. Par exemple, les fichiers téléversés via un formulaire doivent être traités différemment (ils sont accessibles par `request.FILES`, et non pas par `request.POST`). Pour plus de détails sur la façon de gérer des téléversements de fichiers avec un formulaire, consultez Liaison de fichiers téléversés avec un formulaire.

## Formulaires et gabarits

Tout ce qui est nécessaire pour qu’un formulaire soit inclus dans un gabarit est de placer l’instance de formulaire dans le contexte du gabarit. Ainsi, si le formulaire est appelé `form` dans le contexte, `{{ form }}` suffira à afficher ses éléments `<label>` et `<input>` de manière appropriée.

Compléments HTML pour les formulaires dans les gabarits

N’oubliez pas que le rendu HTML d’un formulaire n’inclut pas la balise `<form>` englobante, ni le composant `submit` pour l’envoi du formulaire. C’est à vous d’ajouter ces éléments.

### Gabarits de formulaire réutilisables

La sortie HTML lors de la production d’un formulaire est elle-même générée via un gabarit. Vous pouvez contrôler cette étape en créant un fichier de gabarit approprié et en définissant un `FORM_RENDERER` personnalisé qui utilisera ce paramètre `form_template_name` pour tout le site. Il est aussi possible de personnaliser le processus par formulaire en surchargeant l’attribut `template_name` du formulaire afin de produire le formulaire en utilisant ce gabarit personnalisé, ou en passant le nom de gabarit directement à `Form.render()`.

L’exemple ci-dessous aboutit à ce que `{{ form }}` soit produit au moyen du contenu du gabarit `form_snippet.html`

Dans vos gabarits :

    # In your template:
    {{ form }}

    # In form_snippet.html:
    {% for field in form %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}
        </div>
    {% endfor %}

Puis, vous pouvez configurer le réglage `FORM_RENDERER`:

`settings.py`

    from django.forms.renderers import TemplatesSetting

    class CustomFormRenderer(TemplatesSetting):
        form_template_name = "form_snippet.html"

    FORM_RENDERER = "project.settings.CustomFormRenderer"

… ou pour un seul formulaire

    class MyForm(forms.Form):
        template_name = "form_snippet.html"
        ...

… ou pour une production unique d’une instance de formulaire, en passant le nom du gabarit à la méthode `Form.render()`. Voici un exemple de cette utilisation dans une vue

    def index(request):
        form = MyForm()
        rendered_form = form.render("form_snippet.html")
        context = {"form": rendered_form}
        return render(request, "index.html", context)

Voir Affichage des formulaires en HTML pour plus de détails.

### Gabarits de groupes de champs réutilisables

Each field is available as an attribute of the form, using `{{ form.name_of_field }}` in a template. A field has an `as_field_group()` method which renders the related elements of the field as a group: its label, widget, errors, and help text.

This allows generic templates to be written that arrange each field’s elements in the required layout. For example:

    {{ form.non_field_errors }}
    <div class="fieldWrapper">
      {{ form.subject.as_field_group }}
    </div>
    <div class="fieldWrapper">
      {{ form.message.as_field_group }}
    </div>
    <div class="fieldWrapper">
      {{ form.contact_email.as_field_group }}
    </div>
    <div class="fieldWrapper">
      {{ form.urgent.as_field_group }}
    </div>

Par défaut, Django utilise le gabarit `"django/forms/field.html"` qui est conçu pour être employé avec le style de formulaire par défaut `"django/forms/div.html"`.

Le gabarit par défaut peut être personnalisé en définissant `field_template_name` dans le réglage `FORM_RENDERER` du projet :

    from django.forms.renderers import TemplatesSetting

    class CustomFormRenderer(TemplatesSetting):
        field_template_name = "field_snippet.html"

… ou pour un champ spécifique :

    class MyForm(forms.Form):
        subject = forms.CharField(template_name="my_custom_template.html")
        ...

… ou en fonction de la requête en appelant `BoundField.render()` et en indiquant un nom de gabarit :

    def index(request):
        form = ContactForm()
        subject = form["subject"]
        context = {"subject": subject.render("my_custom_template.html")}
        return render(request, "index.html", context)

### Affichage manuel des champs

Un contrôle plus fin sur le rendu des champs est aussi possible. Cela se ferait probablement dans un gabarit de champ personnalisé, ce qui permet d’écrire le gabarit une seule fois et de le réutiliser pour chaque champ. Cependant, il est aussi possible d’y accéder directement à partir de l’attribut de champ du formulaire. Par exemple :

    {{ form.non_field_errors }}
    <div class="fieldWrapper">
        {{ form.subject.errors }}
        <label for="{{ form.subject.id_for_label }}">Email subject:</label>
        {{ form.subject }}
    </div>
    <div class="fieldWrapper">
        {{ form.message.errors }}
        <label for="{{ form.message.id_for_label }}">Your message:</label>
        {{ form.message }}
    </div>
    <div class="fieldWrapper">
        {{ form.contact_email.errors }}
        <label for="{{ form.contact_email.id_for_label }}">Your email address:</label>
        {{ form.contact_email }}
    </div>
    <div class="fieldWrapper">
        {{ form.urgent.errors }}
        <label for="{{ form.urgent.id_for_label }}">Urgent reply needed?</label>
        {{ form.urgent }}
    </div>

Une balise `<label>` complète peut aussi être générée au moyen de `label_tag()`. Par exemple :

    <div class="fieldWrapper">
        {{ form.subject.errors }}
        {{ form.subject.label_tag }}
        {{ form.subject }}
    </div>

#### Affichage des messages d’erreur de formulaires

Le prix de cette flexibilité est un effort un peu plus grand. Jusqu’à ce stade, nous n’avions pas à nous préoccuper de l’affichage des erreurs du formulaire, car cela se faisait automatiquement. Dans cet exemple, il a fallu s’assurer que les erreurs de chaque champ et les erreurs globales du formulaire soient effectivement affichées. Remarquez `{{ form.non_field_errors }}` au sommet du formulaire ainsi que l’expression de gabarit concernant les erreurs de chaque champ.

La syntaxe `{{ form.nom_du_champ.errors }}` affiche une liste des erreurs du formulaire, sous forme de liste non ordonnée. Cela pourrait ressembler à ceci :

    <ul class="errorlist">
        <li>Contact email is required.</li>
    </ul>

La liste possède une classe CSS `errorlist` pour vous permettre de mettre en forme son apparence. Si vous souhaitez personnaliser davantage l’affichage des erreurs, vous pouvez le faire par une boucle :

    {% if form.subject.errors %}
        <ol>
        {% for error in form.subject.errors %}
            <li><strong>{{ error|escape }}</strong></li>
        {% endfor %}
        </ol>
    {% endif %}

Les erreurs non liées à un champ (ou les erreurs de champs cachés qui sont affichées au sommet du formulaire lorsqu’on utilise des utilitaires comme `form.as_p()`) seront dotées d’une classe supplémentaire `nonfield` pour aider à faire la distinction avec les erreurs spécifiques à un champ. Par exemple, `{{ form.non_field_errors }}` ressemblerait à :

    <ul class="errorlist nonfield">
        <li>Generic validation error</li>
    </ul>

Voir L’API des formulaires pour plus de détails sur les erreurs, la mise en forme et la manipulation des attributs de formulaire dans les gabarits.

### Boucles sur champs de formulaires

Si vous utilisez le même code HTML pour tous vos champs de formulaire, vous pouvez réduire la duplication de code en effectuant une boucle sur chaque champ en utilisant l’opérateur `{% for %}`:

    {% for field in form %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}
            {% if field.help_text %}
              <p class="help" id="{{ field.auto_id }}_helptext">
                {{ field.help_text|safe }}
              </p>
            {% endif %}
        </div>
    {% endfor %}

Voici quelques attributs de champ utiles :

`{{ field.errors }}`

  Affiche une liste `<ul class="errorlist">` contenant toute erreur de validation correspondant à ce champ. Vous pouvez personnaliser la présentation des erreurs avec une boucle `{% for error in field.errors %}`. Dans ce cas, chaque objet de la boucle est une chaîne de caractères contenant le message d’erreur.

`{{ field.field }}`

  L’instance `Field` de la classe de formulaire que cet objet `BoundField` adapte. Vous pouvez l’utiliser pour accéder aux attributs de `Field`, par exemple `{{ char_field.field.max_length }}`.

`{{ field.help_text }}`

  Tout texte d’aide associé au champ.

`{{ field.html_name }}`

  Le nom du champ tel qu’il sera utilisé dans le nom de champ de la balise `input`. Il prend en compte le préfixe de formulaire, si celui-ci est défini.

`{{ field.id_for_label }}`

  The ID that will be used for this field (`id_contact_email` in the example above). If you are constructing the label manually, you may want to use this in lieu of `label_tag`. It’s also useful, for example, if you have some inline JavaScript and want to avoid hardcoding the field’s ID.

`{{ field.is_hidden }}`

  Cet attribut vaut `True` si le champ de formulaire est un champ masqué, sinon il vaut `False`. Ce n’est pas particulièrement utile comme variable de gabarit, mais pourrait être utile dans des tests conditionnels tels que :

    {% if field.is_hidden %}
       {# Do something special #}
    {% endif %}

`{{ field.label }}`

  The label of the field, e.g. `Contact email`.

`{{ field.label_tag }}`

  L’intitulé du champ placé dans la balise HTML `<label>` appropriée. Cela comprend le paramètre `label_suffix` du formulaire. Par exemple, la valeur `label_suffix` par défaut est un caractère deux-points :

      <label for="id_contact_email">Contact email:</label>

`{{ field.legend_tag }}`

  Similaire à `field.label_tag` mais utilise une balise `<legend>` au lieu de `<label>` pour les composants ayant plusieurs entrées enveloppées dans un `<fieldset>`.

`{{ field.use_fieldset }}`

  Cet attribut vaut `True` si le composant du champ de formulaire contient plusieurs entrées qui devraient être sémantiquement groupés dans un `<fieldset>` avec une `<legend>` pour améliorer l’accessibilité. Un exemple d’utilisation dans un gabarit :

    {% if field.use_fieldset %}
      <fieldset>
      {% if field.label %}{{ field.legend_tag }}{% endif %}
    {% else %}
      {% if field.label %}{{ field.label_tag }}{% endif %}
    {% endif %}
    {{ field }}
    {% if field.use_fieldset %}</fieldset>{% endif %}

`{{ field.value }}`

  La valeur du champ, par exemple `quelqu-un@example.com`.

For a complete list of attributes and methods, see the reference guide for `BoundField`.

#### Boucles sur les champs masqués et visibles

Si vous affichez manuellement un formulaire dans un gabarit, sans faire appel à l’affichage par défaut des formulaires de Django, il peut être nécessaire de traiter différemment les champs `<input type="hidden">` des autres champs non masqués. Par exemple, comme les champs masqués ne produisent pas de contenu visible, l’affichage de messages d’erreur « à côté » du champ pourrait générer de la confusion pour les utilisateurs ; il faut donc gérer différemment les erreurs de ce type de champ.

Django fournit deux méthodes qui permettent de tourner en boucle indépendamment sur les champs visibles et masqués : `hidden_fields()` et `visible_fields()`. Voici une modification d’un exemple précédent en utilisant ces deux méthodes :

    {# Include the hidden fields #}
    {% for hidden in form.hidden_fields %}
    {{ hidden }}
    {% endfor %}
    {# Include the visible fields #}
    {% for field in form.visible_fields %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}
        </div>
    {% endfor %}

Cet exemple ne gère pas du tout les erreurs des champs masqués. En principe, une erreur dans un champ masqué est un signe de manipulation abusive d’un formulaire, puisque l’interaction normale avec un formulaire ne les modifie pas. Cependant, vous pourriez facilement ajouter aussi une forme d’affichage pour ces erreurs de formulaire.

## Sujets complémentaires

Cette page aborde les généralités, mais les formulaires peuvent faire bien d’autres choses encore :

- Formulaires groupés
  - Données initiales pour les formulaires groupés
  - Restriction du nombre maximum de formulaires
  - Restriction du nombre maximum de formulaires instanciés
  - Validation des formulaires groupés
  - Validation du nombre de formulaires dans les formulaires groupés
  - Tri et suppression de formulaires
  - Ajout de champs supplémentaires à des formulaires groupés
  - Transmission de paramètres personnalisés aux formulaires de jeux de formulaires
  - Personnalisation du préfixe d’un jeu de formulaires
  - Utilisation des formulaires groupés dans les vues et les gabarits
- Création de formulaires à partir de modèles
  - `ModelForm`
  - Formulaires groupés de modèles
  - Sous-formulaires groupés
- Fichiers annexes de formulaire (classe `Media`)
  - Fichiers annexes définis statiquement
  - `Media` comme propriété dynamique
  - Chemins dans les définitions de fichiers annexes
  - Objets `Media`
  - `Media` pour les formulaires

Voir aussi

La référence des formulaires

  Contient la référence d’API complète, y compris les champs de formulaire, les composants de formulaire et la validation des champs et des formulaires.

django-formtools

  Provides additional form utilities, such as form previews and wizards (documentation).