# Documentation Django 6.0.7

# Composants de formulaires (« widgets »)

Un composant de formulaire est la représentation Django d’un élément de saisie HTML. Le composant se charge de produire le code HTML et d’extraire les données qui lui sont propres dans un dictionnaire GET/POST.

Le code HTML généré par les composants intégrés utilisent la syntaxe HTML5, avec l’en-tête `<!DOCTYPE html>`. Par exemple, les attributs booléens tels que `checked` sont préférés au style XHTML `checked='checked'`.

Astuce

Il ne faut pas confondre les composants avec les champs de formulaires. Ces derniers se chargent de la logique de validation de la saisie et sont directement utilisés dans les gabarits. Les composants de formulaires s’occupent de produire le code HTML des éléments de saisie de formulaire dans les pages web ainsi que de l’extraction de données brutes envoyées. Cependant, les composants de formulaires doivent être attribués aux champs de formulaires.

## Définition des composants

Chaque fois que vous définissez un champ de formulaire, Django utilise un composant par défaut correspondant au type de donnée qui doit être affiché. Pour savoir quel composant est utilisé pour quel champ, consultez la documentation au sujet des Classes de champs Field intégrées.

Cependant, si vous souhaitez utiliser un autre composant pour un champ, utilisez le paramètre `widget` dans la définition du champ. Par exemple :

    from django import forms

    class CommentForm(forms.Form):
        name = forms.CharField()
        url = forms.URLField()
        comment = forms.CharField(widget=forms.Textarea)

Ce code définit un formulaire avec un champ de commentaires utilisant un composant `Textarea` plus grand, plutôt que le composant `TextInput` par défaut.

## Définition de paramètres pour les composants

Beaucoup de composants acceptent des paramètres supplémentaires facultatifs ; ils peuvent être définis lors de l’attribution du composant au champ de formulaire. Dans l’exemple suivant, l’attribut `years` est défini pour un composant `SelectDateWidget`:

    from django import forms

    BIRTH_YEAR_CHOICES = ["1980", "1981", "1982"]
    FAVORITE_COLORS_CHOICES = {
        "blue": "Blue",
        "green": "Green",
        "black": "Black",
    }

    class SimpleForm(forms.Form):
        birth_year = forms.DateField(
            widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES)
        )
        favorite_colors = forms.MultipleChoiceField(
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=FAVORITE_COLORS_CHOICES,
        )

Consultez les composants de formulaires intégrés pour plus d’informations sur les composants disponibles et les paramètres acceptés.

## Personnalisation des instances de composants

Lorsque Django affiche un composant en HTML, le balisage est minimal - Django n’ajoute ni nom de classe, ni d’autres attributs spécifiques au composant. Cela signifie que par exemple tous les composants `TextInput` ont la même apparence sur les pages web.

Il y a deux manières de personnaliser des composants : par instance de composant et par classe de composant.

### Ajout de styles aux instances de composants

Si vous souhaitez qu’une instance de composant apparaisse différemment d’une autre instance, il sera nécessaire d’indiquer des attributs supplémentaires au moment où l’objet composant est instancié et qu’il est attribué à un champ de formulaire (ce qui n’empêche pas d’ajouter aussi certaines règles dans vos fichiers CSS).

Par exemple, en prenant l’exemple de ce formulaire

    from django import forms

    class CommentForm(forms.Form):
        name = forms.CharField()
        url = forms.URLField()
        comment = forms.CharField()

Ce formulaire va inclure des composants `TextInput` pour les champs `name` et `comment` ainsi qu’un composant `URLInput` pour le champ `url`. Leur rendu par défaut est utilisé, pas de classe CSS ni attribut supplémentaire :

    >>> f = CommentForm(auto_id=False)
    >>> print(f)
    <div>Name:<input type="text" name="name" required></div>
    <div>Url:<input type="url" name="url" required></div>
    <div>Comment:<input type="text" name="comment" required></div>

Sur une page web réelle, il est souvent souhaitable d’adapter cet affichage. Le champ commentaire pourrait nécessiter une plus grande zone de saisie, et le composant `name` pourrait être complété par une classe CSS spécifique. Il est aussi possible de définir l’attribut `type` pour utiliser un autre type composant HTML5. Pour cela, utilisez le paramètre `Widget.attrs` lors de la création du composant :

    class CommentForm(forms.Form):
        name = forms.CharField(widget=forms.TextInput(attrs={"class": "special"}))
        url = forms.URLField()
        comment = forms.CharField(widget=forms.TextInput(attrs={"size": "40"}))

Vous pouvez aussi modifier un composant dans la définition du formulaire

    class CommentForm(forms.Form):
        name = forms.CharField()
        url = forms.URLField()
        comment = forms.CharField()

        name.widget.attrs.update({"class": "special"})
        comment.widget.attrs.update(size="40")

Ou si le champ n’est pas directement déclaré dans le formulaire (comme pour les champs de formulaires de modèles), vous pouvez utiliser l’attribut `Form.fields`:

    class CommentForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields["name"].widget.attrs.update({"class": "special"})
            self.fields["comment"].widget.attrs.update(size="40")

Django se chargera ensuite d’inclure les attributs supplémentaires dans le résultat affiché :

    >>> f = CommentForm(auto_id=False)
    >>> print(f)
    <div>Name:<input type="text" name="name" class="special" required></div>
    <div>Url:<input type="url" name="url" required></div>
    <div>Comment:<input type="text" name="comment" size="40" required></div>

Vous pouvez également définir l’attribut HTML `id` à l’aide de `attrs`. Voir `BoundField.id_for_label` pour un exemple.

### Ajout de styles aux classes de composants

Avec les composants, il est possible d’adjoindre des ressources (`css` et `javascript`) et de personnaliser plus encore leur apparence et leur comportement.

Rapidement dit, il est nécessaire de créer une sous-classe du composant et de soit définir une classe internet « Media » ou de créer une propriété « media ».

Ces méthodes impliquent une utilisation relativement avancée de la programmation Python et sont décrites en détails dans le guide thématique des fichiers annexes de formulaires.

## Classes `Widget` de base

Les classes basiques de composants `Widget` et `MultiWidget` sont héritées par tous les composants intégrés et peuvent servir de fondement pour des composants personnalisés.

### `Widget`

class Widget(attrs=None)

  Cette classe abstraite ne peut pas être affichée telle quelle, mais elle fournit l’attribut de base `attrs`. Vous pouvez aussi implémenter ou surcharger la méthode `render()` dans des composants personnalisés.

  attrs

    Un dictionnaire contenant les attributs HTML à définir pour le composant affiché.

        >>> from django import forms
        >>> name = forms.TextInput(attrs={"size": 10, "title": "Your name"})
        >>> name.render("name", "A name")
        '<input title="Your name" type="text" name="name" value="A name" size="10">'

    Si vous attribuez une valeur `True` ou `False` à un attribut, il sera généré comme un attribut HTML5 booléen :

        >>> name = forms.TextInput(attrs={"required": True})
        >>> name.render("name", "A name")
        '<input name="name" type="text" value="A name" required>'
        >>>
        >>> name = forms.TextInput(attrs={"required": False})
        >>> name.render("name", "A name")
        '<input name="name" type="text" value="A name">'

  supports_microseconds

    Un attribut qui vaut `True` par défaut. Si la valeur est `False`, les microsecondes faisant partie des valeurs `datetime` et `time` sont mises à `0`.

  format_value(value)

    Nettoie et renvoie une valeur à utiliser dans le gabarit du composant. `value` n’est pas certain de constituer une saisie valide, il faut donc que les implémentations des sous-classes programment défensivement.

  get_context(name, value, attrs)

    Renvoie un dictionnaire de valeurs à utiliser lors du rendu des gabarits de composants. Par défaut, le dictionnaire contient une seule clé, `'widget'`, qui représente le composant dans un dictionnaire contenant les clés suivantes :

    - `'name'`: le nom du champ en fonction du paramètre `name`.

    - `'is_hidden'`: une valeur booléenne indiquant si ce composant est masqué.

    - `'required'`: une valeur booléenne indiquant si le champ de ce composant est obligatoire.

    - `'value'`: la valeur telle que renvoyée par `format_value()`.

    - `'attrs'`: les attributs HTML à définir sur le composant final. Combinaison de l’attribut `attrs` et du paramètre `attrs`.

    - `'template_name'`: la valeur de `self.template_name`.

    Les sous-classes de `Widget` peuvent fournir des valeurs de contexte personnalisées en surchargeant cette méthode.

  id_for_label(id_)

    Renvoie l’attribut HTML `id` de ce composant à l’usage de la balise `<label>`, en fonction de l’attribut `id` du champ. Renvoie une chaîne vide si `id` n’est pas disponible.

    Ce point d’entrée est nécessaire car certains composants possèdent plusieurs éléments HTML et donc plusieurs `id`. Dans ce cas, cette méthode doit renvoyer une valeur `id` qui correspond au premier `id` dans les balises du composant.

  render(name, value, attrs=None, renderer=None)

    Produit un composant en HTML en utilisant le moteur de rendu donné. Si `renderer` vaut `None`, le moteur de rendu du réglage `FORM_RENDERER` est utilisé.

  value_from_datadict(data, files, name)

    Étant donné un dictionnaire de données et le nom de ce composant, renvoie la valeur du composant. `files` peut contenir des données provenant de `request.FILES`. Renvoie `None` si aucune valeur n’est disponible. Notez également que `value_from_datadict` peut être appelée plus d’une fois pendant le traitement des données de formulaire, ce qui signifie que si vous la personnalisez en ajoutant du traitement lourd, vous devriez implémenter vous-même un mécanisme de cache.

  value_omitted_from_data(data, files, name)

    Étant donné les dictionnaires `data` et `files` ainsi que le nom de ce composant, indique s’il existe des données ou des fichiers pour le composant.

    Le résultat de cette méthode détermine si un champ d’un formulaire de modèle prend sa valeur par défaut.

    Les composants `CheckboxInput`, `CheckboxSelectMultiple` et `SelectMultiple` sont des cas particuliers où la méthode renvoie toujours `False` car une case à cocher non cochée ou un `<select multiple>` sans sélection n’apparassent pas dans les données soumises par le formulaire HTML, ce qui fait qu’il est impossible de savoir si un utilisateur a saisi une valeur ou non.

  use_fieldset

    Un attribut pour savoir si le composant doit être contenu dans un `<fieldset>` avec une balise `<legend>` lorsqu’il est produit. Vaut `False` par défaut, mais `True` lorsque le composant contient plusieurs balises `<input>`, tels que pour les composants `CheckboxSelectMultiple`, `RadioSelect`, `MultiWidget`, `SplitDateTimeWidget` et `SelectDateWidget`.

  use_required_attribute(initial)

    Étant donné une valeur `initial` d’un champ de formulaire, renvoie si oui ou non le rendu du composant doit comporter l’attribut HTML `required`. Les formulaires utilisent cette méthode en compagnie de `Field.required` et de `Form.use_required_attribute` pour déterminer s’ils doivent afficher l’attribut `required` pour chacun de leurs champs.

    Renvoie `False` par défaut pour les composants masqués, sinon `True`. Il y a des cas particuliers : `FileInput` et `ClearableFileInput` renvoient `False` lorsque `initial` est défini et `CheckboxSelectMultiple` renvoie toujours `False` car la validation des navigateurs exigerait que toutes les cases soient cochées au lieu de simplement une seule.

    Override this method in custom widgets that aren’t compatible with browser validation. For example, a WYSIWYG text editor widget backed by a hidden `textarea` element may want to always return `False` to avoid browser validation on the hidden field.

### `MultiWidget`

class MultiWidget(widgets, attrs=None)

  Un composant formé de plusieurs composants. `MultiWidget` fonctionne de concert avec le champ `MultiValueField`.

  `MultiWidget` requiert un paramètre :

  widgets

    Un objet itérable contenant les composants nécessaires. Par exemple :

        >>> from django.forms import MultiWidget, TextInput
        >>> widget = MultiWidget(widgets=[TextInput, TextInput])
        >>> widget.render("name", ["john", "paul"])
        '<input type="text" name="name_0" value="john"><input type="text" name="name_1" value="paul">'

    Vous pouvez fournir un dictionnaire afin d’indiquer des suffixes personnalisés pour l’attribut `name` de chaque sous-composant. Dans ce cas, pour chaque paire `(clé, composant)`, la clé sera ajoutée au nom `name` du composant pour générer la valeur de l’attribut. Il est possible d’indiquer une seule clé avec une chaîne vide (`''`) pour demander la suppression du suffixe d’un des composants. Par exemple :

        >>> widget = MultiWidget(widgets={"": TextInput, "last": TextInput})
        >>> widget.render("name", ["john", "paul"])
        '<input type="text" name="name" value="john"><input type="text" name="name_last" value="paul">'

  Ainsi qu’une méthode obligatoire :

  decompress(value)

    Cette méthode accepte une seule valeur « compressée » à partir du champ et renvoie une liste de valeurs « décompressées ». La valeur d’entrée peut être considérée comme valide, mais pourrait être vide.

    Cette méthode doit être implémentée par la sous-classe, et comme la valeur peut être vide, l’implémentation doit être défensive.

    La logique de la « décompression » est qu’il est nécessaire de « scinder » la valeur combinée du champ de formulaire en valeurs distinctes pour chaque composant.

    Un exemple pour illustrer ce processus est la façon dont `SplitDateTimeWidget` transforme une valeur `datetime` en une liste où la date et l’heure sont séparées :

        from django.forms import MultiWidget

        class SplitDateTimeWidget(MultiWidget):
            # ...

            def decompress(self, value):
                if value:
                    return [value.date(), value.time()]
                return [None, None]

    Astuce

    Notez que `MultiValueField` possède une méthode complémentaire `compress()` qui joue le rôle inverse, combiner les valeurs nettoyées de tous les sous-composants en une seule valeur.

  Il fournit un contenu de contexte spécifique :

  get_context(name, value, attrs)

    En plus de la clé `'widget'` décrite dans `Widget.get_context()`, `MultiWidget` ajoute une clé `widget['subwidgets']`.

    Il est possible d’effectuer cette boucle dans le gabarit du composant :

        {% for subwidget in widget.subwidgets %}
            {% include subwidget.template_name with widget=subwidget %}
        {% endfor %}

  Voici un exemple de composant héritant de `MultiWidget` qui affiche une date avec le jour, le mois et l’année dans des listes déroulantes différentes. Ce composant est prévu pour être utilisé avec un champ `DateField` plutôt qu’avec un `MultiValueField`, c’est pourquoi nous avons implémenté `value_from_datadict()`:

      from datetime import date
      from django import forms

      class DateSelectorWidget(forms.MultiWidget):
          def __init__(self, attrs=None):
              days = {day: day for day in range(1, 32)}
              months = {month: month for month in range(1, 13)}
              years = {year: year for year in [2018, 2019, 2020]}
              widgets = [
                  forms.Select(attrs=attrs, choices=days),
                  forms.Select(attrs=attrs, choices=months),
                  forms.Select(attrs=attrs, choices=years),
              ]
              super().__init__(widgets, attrs)

          def decompress(self, value):
              if isinstance(value, date):
                  return [value.day, value.month, value.year]
              elif isinstance(value, str):
                  year, month, day = value.split("-")
                  return [day, month, year]
              return [None, None, None]

          def value_from_datadict(self, data, files, name):
              day, month, year = super().value_from_datadict(data, files, name)
              # DateField expects a single string that it can parse into a date.
              return "{}-{}-{}".format(year, month, day)

  Le constructeur crée plusieurs composants `Select` dans une liste. La méthode `super()` utilise cette liste pour configurer le composant.

  La méthode obligatoire `decompress()` partage une valeur `datetime.date` en valeurs distinctes de jour, mois et année correspondant à chaque composant. Si une date non valable a été choisie, comme par exemple un 30 février, `DateField` passe alors une chaîne à cette méthode qui doit l’analyser. Le `return` final gère le cas de la valeur `None`, qui signifie que nous n’avons aucune valeur par défaut pour nos sous-composants.

  Lîmplémentation par défaut de `value_from_datadict()` renvoie une liste de valeurs correspondant à chaque `Widget`. C’est le comportement correct lorsqu’un composant `MultiWidget` est utilisé de concert avec un champ `MultiValueField`. Mais comme nous voulons utiliser ce composant avec un champ `DateField`, qui n’accepte qu’une seule valeur, nous avons surchargé cette méthode. L’implémentation ici combine les données des sous-composants en une chaîne mise en forme selon l’attente de `DateField`.

## Composants intégrés

Dans son module `django.forms.widgets`, Django fournit une représentation de tous les composants HTML de base, plus certains groupes de composants fréquemment utilisés, y compris la saisie de texte, diverses cases à cocher et listes à choix, l’envoi de fichiers et le traitement de saisies à plusieurs valeurs.

### Composants chargés de la saisie de texte

Ces composants font usage des éléments HTML `input` et `textarea`.

#### `TextInput`

class TextInput

  - `input_type`: `'text'`

  - `template_name`: `'django/forms/widgets/text.html'`

  - Produit : `<input type="text" ...>`

#### `NumberInput`

class NumberInput

  - `input_type`: `'number'`

  - `template_name`: `'django/forms/widgets/number.html'`

  - Produit : `<input type="number" ...>`

  Il faut savoir que certains navigateurs ne gèrent pas correctement la saisie de nombres régionalisés dans les types de zones `number`. Django lui-même évite de les utiliser pour les champs dont la propriété `localize` est `True`.

#### `EmailInput`

class EmailInput

  - `input_type`: `'email'`

  - `template_name`: `'django/forms/widgets/email.html'`

  - Produit : `<input type="email" ...>`

#### `URLInput`

class URLInput

  - `input_type`: `'url'`

  - `template_name`: `'django/forms/widgets/url.html'`

  - Produit : `<input type="url" ...>`

#### `ColorInput`

class ColorInput

  - `input_type`: `'color'`

  - `template_name`:`'django/forms/widgets/color.html'`

  - Produit : `<input type="color" ...>`

#### `SearchInput`

class SearchInput

  - `input_type`: `'search'`

  - `template_name`: `'django/forms/widgets/search.html'`

  - Produit : `<input type="search" ...>`

#### `TelInput`

class TelInput

  - `input_type`: `'tel'`

  - `template_name`: `'django/forms/widgets/tel.html'`

  - Produit : `<input type="tel" ...>`

  Les navigateurs n’effectuent aucune vérification côté client par défaut car les formats de numéros de téléphone varient énormément de par le monde. Vous pouvez en ajouter vous-même en définissant `pattern`, `minlength` ou `maxlength` dans l’argument `Widget.attrs`.

  De plus, vous pouvez ajouter de la validation côté serveur à votre champ de formulaire avec un validateur du type `RegexValidator` ou par des paquets tiers, tels que django-phonenumber-field.

#### `PasswordInput`

class PasswordInput

  - `input_type`: `'password'`

  - `template_name`: `'django/forms/widgets/password.html'`

  - Produit : `<input type="password" ...>`

  Accepte un paramètre facultatif :

  render_value

    Détermine si le composant contient une valeur lorsque le formulaire est réaffiché après une erreur de validation (la valeur par défaut est `False`).

#### `HiddenInput`

class HiddenInput

  - `input_type`: `'hidden'`

  - `template_name`: `'django/forms/widgets/hidden.html'`

  - Produit : `<input type="hidden" ...>`

  Notez qu’il existe également un composant `MultipleHiddenInput` qui regroupe un ensemble de zones de saisie masquées.

#### `DateInput`

class DateInput

  - `input_type`: `'text'`

  - `template_name`: `'django/forms/widgets/date.html'`

  - Produit : `<input type="text" ...>`

  Accepte les mêmes paramètres que `TextInput`, avec en plus un paramètre facultatif :

  format

    Le format dans lequel la valeur initiale du champ est affichée.

  Si aucun paramètre `format` n’est indiqué, le format par défaut est le premier format trouvé dans `DATE_INPUT_FORMATS` en respectant la Régionalisation des formats. Les formats %U`, `%W` et `%j` ne sont pas pris en charge par ce composant.

  Utilisation du type de champ de saisie HTML5 « date »

  Si vous ciblez des navigateurs qui prennent en charge le type de champ de saisie HTML5 « date », vous pouvez surcharger l’attribut `input_type` pour activer le sélecteur de date natif du navigateur :

      class MyDateInput(forms.DateInput):
          input_type = "date"
          format = "%Y-%m-%d"

  Ou alors :

      DateInput(attrs={"type": "date"}, format="%Y-%m-%d")

  HTML5 date inputs expect values in the ISO format `YYYY-MM-DD`. If a different format is provided, the field may appear empty even when a value exists. Setting the `format` attribute controls how Django provides the value, but the browser controls how it is displayed. Hence, the `format` attribute and the `DATE_INPUT_FORMATS` setting will have no effect on the displayed value.

#### `DateTimeInput`

class DateTimeInput

  - `input_type`: `'text'`

  - `template_name`: `'django/forms/widgets/datetime.html'`

  - Produit : `<input type="text" ...>`

  Accepte les mêmes paramètres que `TextInput`, avec en plus un paramètre facultatif :

  format

    Le format dans lequel la valeur initiale du champ est affichée.

  Si aucun paramètre `format` n’est indiqué, le format par défaut est le premier format trouvé dans `DATETIME_INPUT_FORMATS` en respectant la Régionalisation des formats. Les formats %U`, `%W` et `%j` ne sont pas pris en charge par ce composant.

  Par défaut, la partie microsecondes de la valeur de temps est toujours définie à `0`. Si les microsecondes sont nécessaires, créez une sous-classe avec l’attribut `supports_microseconds` défini à `True`.

#### `TimeInput`

class TimeInput

  - `input_type`: `'text'`

  - `template_name`: `'django/forms/widgets/time.html'`

  - Produit : `<input type="text" ...>`

  Accepte les mêmes paramètres que `TextInput`, avec en plus un paramètre facultatif :

  format

    Le format dans lequel la valeur initiale du champ est affichée.

  Si aucun paramètre `format` n’est indiqué, le format par défaut est le premier format trouvé dans `TIME_INPUT_FORMATS` en respectant la Régionalisation des formats.

  Pour le traitement des microsecondes, référez-vous à `DateTimeInput`.

#### `Textarea`

class Textarea

  - `template_name`: `'django/forms/widgets/textarea.html'`

  - Produit : `<textarea>...</textarea>`

### Composants cases à cocher et listes à choix

Ces composants font usage des éléments HTML `<select>`, `<input type='checkbox'>` et `<input type='radio'>`.

Les composants qui produisent plusieurs options de choix possèdent un attribut `option_template_name` qui indique le gabarit à utiliser pour produire chaque choix. Par exemple, pour le composant `Select`, `select_option.html` produit une `<option>` dans un `<select>`.

#### `CheckboxInput`

class CheckboxInput

  - `input_type`: `'checkbox'`

  - `template_name`: `'django/forms/widgets/checkbox.html'`

  - Produit : `<input type="checkbox" ...>`

  Accepte un paramètre facultatif :

  check_test

    Un objet exécutable acceptant la valeur de `CheckboxInput` et renvoyant `True` si la case à cocher doit apparaître cochée pour cette valeur.

#### `Select`

class Select

  - `template_name`: `'django/forms/widgets/select.html'`

  - `option_template_name`: `'django/forms/widgets/select_option.html'`

  - Produit : `<select><option ...>...</select>`

  choices

    Cet attribut est facultatif lorsque le champ de formulaire n’a pas d’attribut `choices`. Si l’attribut de champ est présent, il écrase tout ce que vous pourriez définir ici au moment où l’attribut est mis à jour au niveau du champ `Field`.

#### `NullBooleanSelect`

class NullBooleanSelect

  - `template_name`: `'django/forms/widgets/select.html'`

  - `option_template_name`: `'django/forms/widgets/select_option.html'`

  Composant de liste à choix avec les options « Inconnu », « Oui » et « Non »

#### `SelectMultiple`

class SelectMultiple

  - `template_name`: `'django/forms/widgets/select.html'`

  - `option_template_name`: `'django/forms/widgets/select_option.html'`

  Semblable à `Select`, mais autorise les sélections multiples : `<select multiple>…</select>`

#### `RadioSelect`

class RadioSelect

  - `template_name`: `'django/forms/widgets/radio.html'`

  - `option_template_name`: `'django/forms/widgets/radio_option.html'`

  Semblable à `Select`, mais affiché sous forme de liste de boutons radio dans des balises `<div>`:

      <div>
        <div><input type="radio" name="..."></div>
        ...
      </div>

  Pour un contrôle plus fin du balisage produit, vous pouvez passer en boucle les boutons radio dans le gabarit. En prenant comme exemple un formulaire `myform` avec un champ `beatles` utilisant un composant `RadioSelect`:

      <fieldset>
          <legend>{{ myform.beatles.label }}</legend>
          {% for radio in myform.beatles %}
          <div class="myradio">
              {{ radio }}
          </div>
          {% endfor %}
      </fieldset>

  Cela produirait le code HTML suivant :

      <fieldset>
          <legend>Radio buttons</legend>
          <div class="myradio">
              <label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" required> John</label>
          </div>
          <div class="myradio">
              <label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required> Paul</label>
          </div>
          <div class="myradio">
              <label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" required> George</label>
          </div>
          <div class="myradio">
              <label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required> Ringo</label>
          </div>
      </fieldset>

  Les balises `<label>` y figurent également. Pour un contrôle encore plus fin, vous pouvez utiliser les attributs `tag`, `choice_label` et `id_for_label` de chaque bouton radio. Par exemple, ce gabarit…

      <fieldset>
          <legend>{{ myform.beatles.label }}</legend>
          {% for radio in myform.beatles %}
          <label for="{{ radio.id_for_label }}">
              {{ radio.choice_label }}
              <span class="radio">{{ radio.tag }}</span>
          </label>
          {% endfor %}
      </fieldset>

  …produit le code HTML suivant :

      <fieldset>
          <legend>Radio buttons</legend>
          <label for="id_beatles_0">
              John
              <span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" required></span>
          </label>
          <label for="id_beatles_1">
              Paul
              <span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required></span>
          </label>
          <label for="id_beatles_2">
              George
              <span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" required></span>
          </label>
          <label for="id_beatles_3">
              Ringo
              <span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required></span>
          </label>
      </fieldset>

  Si vous décidez de ne pas passer en boucle les boutons radio, par exemple si le gabarit contient `{{ myform.beatles }}`, ils seront contenus dans un élément `<div>` avec des balises `<div>`, comme ci-dessus.

  Le conteneur `<div>` supérieur reçoit l’attribut `id` du composant, si défini, ou `BoundField.auto_id` dans le cas contraire.

  Lors de l’itération sur les boutons radio, les balises``label`` and `input` incluent les attributs `for` et `id`, respectivement. Chaque bouton radio inclut un attribut `id_for_label` produisant l’ID de l’élément.

#### `CheckboxSelectMultiple`

class CheckboxSelectMultiple

  - `template_name`: `'django/forms/widgets/checkbox_select.html'`

  - `option_template_name`: `'django/forms/widgets/checkbox_option.html'`

  Semblable à `SelectMultiple`, mais affiché sous forme de liste de cases à cocher :

      <div>
        <div><input type="checkbox" name="..." ></div>
        ...
      </div>

  Le conteneur `<div>` supérieur reçoit l’attribut `id` du composant, si défini, ou `BoundField.auto_id` dans le cas contraire.

Comme pour `RadioSelect`, il est possible de parcourir en boucle les cases à cocher individuelles pour obtenir les choix du composant. Au contraire de `RadioSelect`, les cases à cocher n’incluront pas l’attribut HTML `required` si le champ est obligatoire car la validation des navigateurs exigerait alors que toutes les cases soient cochées au lieu d’au moins une.

Lors de l’itération sur les cases à cocher, les balises``label`` and `input` incluent les attributs `for` et `id`, respectivement. Chaque case à cocher inclut un attribut `id_for_label` produisant l’ID de l’élément.

### Composants d’envoi de fichier

#### `FileInput`

class FileInput

  - `template_name`: `'django/forms/widgets/file.html'`

  - Produit : `<input type="file" ...>`

#### `ClearableFileInput`

class ClearableFileInput

  - `template_name`: `'django/forms/widgets/clearable_file_input.html'`

  - Produit : `<input type="file" ...>`, avec une case à cocher supplémentaire pour effacer la valeur du champ, si le champ n’est pas obligatoire et qu’il comporte une donnée initiale.

### Composants multiples

#### `MultipleHiddenInput`

class MultipleHiddenInput

  - `template_name`: `'django/forms/widgets/multiple_hidden.html'`

  - Produit : plusieurs balises `<input type="hidden" ...>`

  Un composant qui gère plusieurs composants masqués pour des champs qui possèdent une liste de valeurs.

#### `SplitDateTimeWidget`

class SplitDateTimeWidget

  - `template_name`: `'django/forms/widgets/splitdatetime.html'`

  Composant parent (sous-classe de `MultiWidget`) de deux composants : `DateInput` pour la date et `TimeInput` pour l’heure. Doit être utilisé avec `SplitDateTimeField` et non pas `DateTimeField`.

  `SplitDateTimeWidget` contient plusieurs paramètres facultatifs :

  date_format

    Semblable à `DateInput.format`

  time_format

    Semblable à `TimeInput.format`

  date_attrs
  time_attrs

    Semblable à `Widget.attrs`. Un dictionnaire contenant des attributs HTML à définir respectivement sur les composants `DateInput` et `TimeInput`. Si ces attributs ne sont pas définis, c’est `Widget.attrs` qui est utilisé à la place.

#### `SplitHiddenDateTimeWidget`

class SplitHiddenDateTimeWidget

  - `template_name`: `'django/forms/widgets/splithiddendatetime.html'`

  Semblable à `SplitDateTimeWidget`, mais utilise `HiddenInput` à la fois pour la date et l’heure.

#### `SelectDateWidget`

class SelectDateWidget

  - `template_name`: `'django/forms/widgets/select_date.html'`

  Composant parent de trois sous-composants `Select` pour le mois, le jour et l’année.

  Accepte plusieurs paramètres facultatifs :

  years

    Une liste (ou tuple) facultative d’années à présenter dans la liste à choix « year ». La valeur par défaut est une liste contenant l’année en cours et les 9 années suivantes.

  months

    Un dictionnaire de mois facultatif à utiliser dans la liste déroulante « mois ».

    Les clés du dictionnaire correspondent au numéro du mois (indice à partir de 1) et les valeurs sont les mois affichés :

        MONTHS = {
            1: _("jan"),
            2: _("feb"),
            3: _("mar"),
            4: _("apr"),
            5: _("may"),
            6: _("jun"),
            7: _("jul"),
            8: _("aug"),
            9: _("sep"),
            10: _("oct"),
            11: _("nov"),
            12: _("dec"),
        }

  empty_label

    Si le champ `DateField` n’est pas obligatoire, `SelectDateWidget` comportera un choix vide au sommet de la liste (qui s’affiche comme `---` par défaut). Vous pouvez modifier le texte de ce choix avec l’attribut `empty_label`. `empty_label` peut être une chaîne, une liste ou un tuple. Lorsqu’une chaîne est utilisée, toutes les listes de choix auront chacune un choix vide avec ce contenu. Si `empty_label` est une liste ou un tuple de 3 éléments textuels, les listes de choix possèdent chacune leur propre contenu. Les textes doivent apparaître dans cet ordre : `('texte_année', 'texte_mois', 'texte_jour')`.

        # A custom empty label with string
        field1 = forms.DateField(widget=SelectDateWidget(empty_label="Nothing"))

        # A custom empty label with tuple
        field1 = forms.DateField(
            widget=SelectDateWidget(
                empty_label=("Choose Year", "Choose Month", "Choose Day"),
            ),
        )