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 :
obtenir l’élément dans la vue (le récupérer à partir de la base de données, par exemple)
le transmettre au contexte de gabarit
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 :
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 :
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 :
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
Le formulaire précédent comportait un seul champ, your_name
, de type CharField
. Dans ce cas, le formulaire possède quatre champs : subject
, message
, sender
et cc_myself
. CharField
, EmailField
et BooleanField
ne sont que trois des types de champs disponibles ; une liste complète se trouve dans 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.
Dans l’exemple ci-dessus du formulaire de contact, cc_myself
sera une valeur booléenne. De la même manière, des champs de type IntegerField
et FloatField
convertissent les valeurs en types Python int
et float
, respectivement.
Voici comment les données de formulaire pourraient être traitées dans la vue qui gère ce formulaire :
from django.core.mail import send_mail
if form.is_valid():
subject = form.cleaned_data["subject"]
message = form.cleaned_data["message"]
sender = form.cleaned_data["sender"]
cc_myself = form.cleaned_data["cc_myself"]
recipients = ["info@example.com"]
if cc_myself:
recipients.append(sender)
send_mail(subject, message, sender, recipients)
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
:
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¶
Chaque champ est disponible comme attribut du formulaire, utilisant la syntaxe {{ form.name_of_field }}
dans un gabarit. Un champ possède une méthode:meth:~django.forms.BoundField.as_field_group qui produit les éléments liés au champ sous forme de groupe :, son étiquette, son composant, les éventuelles erreurs ou le texte d’aide.
Cela permet d’écrire des gabarits génériques qui composent les éléments des champs dans la disposition voulue. Par exemple :
{{ 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.sender.as_field_group }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.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.sender.errors }}
<label for="{{ form.sender.id_for_label }}">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
{{ form.cc_myself }}
</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>Sender 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 objetBoundField
adapte. Vous pouvez l’utiliser pour accéder aux attributs deField
, 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 }}
L’attribut
id
utilisé pour ce champ (id_email
dans l’exemple ci-dessus). Si vous construisez vous-même l’étiquette du champ, il peut être avantageux d’utiliser ceci à la place delabel_tag
. C’est aussi utile par exemple si vous avez du code JavaScript en ligne et que vous vouliez éviter de figer l’identifiant du champ.{{ field.is_hidden }}
Cet attribut vaut
True
si le champ de formulaire est un champ masqué, sinon il vautFalse
. 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 }}
L’étiquette du champ, par exemple
Adresse de courriel
.{{ field.label_tag }}
L’intitulé du champ placé dans la balise HTML
<label>
appropriée. Cela comprend le paramètrelabel_suffix
du formulaire. Par exemple, la valeurlabel_suffix
par défaut est un caractère deux-points :<label for="id_email">Email address:</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
.
Voir aussi
Pour une liste complète des attributs et méthodes, voir BoundField
.
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
- Fichiers annexes de formulaire (classe
Media
)
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.