Le composant Form de Django offre une solution intégrée pour gérer les formulaires dans les applications web. Il génère automatiquement les balises HTML des champs de saisie, applique des validations sur les données utilisateur et conserve les valeurs entrées en cas d'erreurs de soumissino.
Exemple basique sans le composant Form
Dans la vue :
def vue_connexion(request):
message_erreur = ""
if request.method == "POST":
identifiant = request.POST.get("identifiant")
motdepasse = request.POST.get("motdepasse")
if identifiant == "admin" and motdepasse == "motdepasse123":
return HttpResponse("Authentification réussie")
else:
message_erreur = "Identifiants incorrects"
return render(request, "connexion.html", {"message_erreur": message_erreur})
Dans le template :
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Page de connexion</title>
<style>
.erreur { color: red; }
</style>
</head>
<body>
<form action="/connexion/" method="post">
{% csrf_token %}
<p>
<label for="identifiant">Identifiant</label>
<input type="text" name="identifiant" id="identifiant">
</p>
<p>
<label for="motdepasse">Mot de passe</label>
<input type="password" name="motdepasse" id="motdepasse">
<span class="erreur"></span>
</p>
<p>
<input type="submit">
<span class="erreur">{{ message_erreur }}</span>
</p>
</form>
</body>
</html>
Implémentation avec le composant Form
Créer une classe de formulaire :
from django import forms
class FormulaireAuthentification(forms.Form):
identifiant = forms.CharField(min_length=8, label="Identifiant")
motdepasse = forms.CharField(min_length=6, label="Mot de passe")
Intégration dans la vue :
def vue_connexion_form(request):
formulaire = FormulaireAuthentification()
message_erreur = ""
if request.method == "POST":
formulaire = FormulaireAuthentification(request.POST)
if formulaire.is_valid():
identifiant = formulaire.cleaned_data.get("identifiant")
motdepasse = formulaire.cleaned_data.get("motdepasse")
if identifiant == "admin" and motdepasse == "motdepasse123":
return HttpResponse("Authentification réussie")
else:
message_erreur = "Identifiants incorrects"
return render(request, "connexion_form.html", {"formulaire": formulaire, "message_erreur": message_erreur})
Template associé :
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Connexion avec Form</title>
<style>
.erreur { color: red; }
</style>
</head>
<body>
<form action="/connexion_form/" method="post" novalidate>
{% csrf_token %}
<p>
{{ formulaire.identifiant.label }}
{{ formulaire.identifiant }}
<span class="erreur">{{ formulaire.identifiant.errors.0 }}</span>
</p>
<p>
{{ formulaire.motdepasse.label }}
{{ formulaire.motdepasse }}
<span class="erreur">{{ formulaire.motdepasse.errors.0 }}</span>
</p>
<p>
<input type="submit">
<span class="erreur">{{ message_erreur }}</span>
</p>
</form>
</body>
</html>
Configuration des champs courants
Valeur initiale : Le paramètre initial définit une valeur par défaut dans le champ.
class FormulaireInscription(forms.Form):
nom = forms.CharField(min_length=5, label="Nom complet", initial="Jean Dupont")
courriel = forms.EmailField(label="Adresse email")
Messages d'erreur personnalisés : Redéfinir les messages via error_messages.
class FormulaireInscription(forms.Form):
nom = forms.CharField(
min_length=5,
label="Nom complet",
initial="Jean Dupont",
error_messages={
"required": "Ce champ est obligatoire",
"invalid": "Format invalide",
"min_length": "Minimum 5 caractères"
}
)
courriel = forms.EmailField(label="Adresse email")
Champ mot de passe : Utiliser un widget spécifique pour masquer la saisie.
class FormulaireInscription(forms.Form):
motdepasse = forms.CharField(
min_length=8,
label="Mot de passe",
widget=forms.widgets.PasswordInput(attrs={'class': 'input-style'}, render_value=True)
)
Boutons radio : Sélection unique avec des options.
class FormulaireProfil(forms.Form):
genre = forms.fields.ChoiceField(
choices=((1, "Homme"), (2, "Femme"), (3, "Autre")),
label="Genre",
initial=3,
widget=forms.widgets.RadioSelect
)
Listes déroulantes : Sélection unique ou multiple.
class FormulaireInteret(forms.Form):
activite = forms.fields.ChoiceField(
choices=((1, "Sport"), (2, "Lecture"), (3, "Musique")),
label="Activité préférée",
initial=2,
widget=forms.widgets.Select
)
langues = forms.fields.MultipleChoiceField(
choices=((1, "Français"), (2, "Anglais"), (3, "Espagnol")),
label="Langues parlées",
initial=[1, 2],
widget=forms.widgets.SelectMultiple
)
Cases à cocher : Pour des options booléennes ou multilpes.
class FormulairePreferences(forms.Form):
souvenir = forms.fields.ChoiceField(
label="Se souvenir de moi",
initial="checked",
widget=forms.widgets.CheckboxInput
)
hobbies = forms.fields.MultipleChoiceField(
choices=((1, "Cuisine"), (2, "Jardinage"), (3, "Cinéma")),
label="Hobbies",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple
)
Remarque sur les choix dynamiques : Pour des options provenant d'une base de données, surcharger la méthode __init__ afin de mettre à jour les choix.
from django.forms import Form, fields, widgets
class FormulaireDynamique(Form):
categorie = fields.ChoiceField(widget=widgets.Select)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['categorie'].widget.choices = [(obj.id, obj.nom) for obj in ModeleCategorie.objects.all()]
Techniques de validation
Validation par expression régulière : Utiliser RegexValidator pour des motifs personnalisés.
from django.forms import Form, fields
from django.core.validators import RegexValidator
class FormulaireCoordonnees(Form):
telephone = fields.CharField(
validators=[RegexValidator(r'^\d{10}$', 'Numéro de téléphone invalide')],
label="Téléphone"
)
Validation personnalisée : Créer une fonction de validation et l'appliquer via validators.
import re
from django.forms import Form, fields, widgets
from django.core.exceptions import ValidationError
def valider_code_postal(valeur):
if not re.match(r'^\d{5}$', valeur):
raise ValidationError("Code postal invalide")
class FormulaireAdresse(Form):
codepostal = fields.CharField(
validators=[valider_code_postal],
label="Code postal",
error_messages={'required': 'Ce champ est requis'}
)
ville = fields.CharField(label="Ville")
Intégration avec Bootstrap
Appliquer des classes Bootstrap pour améliorer l'apparence des formulaires.
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Inscription Bootstrap</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<form method="post" novalidate class="form-horizontal">
{% csrf_token %}
<div class="form-group">
<label for="{{ formulaire.identifiant.id_for_label }}" class="col-md-3 control-label">{{ formulaire.identifiant.label }}</label>
<div class="col-md-9">
{{ formulaire.identifiant }}
<span class="help-block text-danger">{{ formulaire.identifiant.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{ formulaire.motdepasse.id_for_label }}" class="col-md-3 control-label">{{ formulaire.motdepasse.label }}</label>
<div class="col-md-9">
{{ formulaire.motdepasse }}
<span class="help-block text-danger">{{ formulaire.motdepasse.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-3 col-md-9">
<button type="submit" class="btn btn-primary">Valider</button>
</div>
</div>
</form>
</div>
<script src="/static/jquery.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
Ajout massif de styles : Surcharger la méthode __init__ pour attribuer des classes à tous les champs.
class FormulaireStyle(forms.Form):
identifiant = forms.CharField(label="Identifiant")
motdepasse = forms.CharField(label="Mot de passe")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for champ in self.fields.values():
champ.widget.attrs.update({'class': 'form-control'})