Résolue

Forms.ValidationError ne fonctionne pas !

# Affichage # Django # HTML

Bonjour,

J'ai longuement lu et relu mon code je j'arrive pas afficher le message d'erreur dans ma page HTML. J'ai mis un print() comme vous pouvez le constater au dessus de mon raise, dans mon console le message d'erreur s'affiche donc on passe bien dans ma condition...

class SignupForm(forms.Form):
    pseudo = forms.CharField(max_length=8, required=False)
    email = forms.EmailField()
    password = forms.CharField(min_length=6)
    job = forms.ChoiceField(choices=JOBS)
    cgu_accept = forms.BooleanField(initial=True)


    def clean_pseudo(self):
        pseudo = self.cleaned_data.get("pseudo")
        if "?" in pseudo:
            print("erreur?")
            raise forms.ValidationError("Le message ne peut conteni")
        return pseudo

Ou est-ce que je dois chercher pour trouvé le petit defaut ?

Merci de votre aide.

Bonne journée.

Salut,

Je pense que le problème ne vient pas de ta fonction clean_pseudo ou de ta condition (d'ailleurs c'est sûr car ton print affiches bien quelque chose =D ). Ton raise forms.ValidationError est correct aussi si tu veux signaler une erreur.

Par contre, le truc c'est que ces messages d'erreur sont gérés par le formulaire Django lui-même et ne sont pas simplement imprimés dans la console ou envoyés à l'utilisateur. Ils sont en fait ajoutés à un dictionnaire spécial appelé form.errors. Pour afficher le message d'erreur dans ta page HTML, tu devras le faire explicitement.

Si tu utilises un rendu de formulaire standard (c'est-à-dire la méthode {{ form.as_p }} dans ton HTML), alors Django générera automatiquement les balises HTML correspondant aux messages d'erreur. Sinon, tu peux accéder à l'erreur spécifique de chaque champ en utilisant {{ form.pseudo.errors }} dans ton template.

Vérifie ton template HTML, c'est là que la magie du message d'erreur doit se produire. Tiens-nous au courant si ça fonctionne !

Bonne chance et bonne journée à toi aussi !

Bonjour,

Merci pour ton retour. Au départ j'ai mis dans mon template {{ form }} j'ai eu un belle espoir en voyant ta réponse que j'ai modifié en {{ form.as_p }}. Mais cela ne fonctionne toujours pas, j'ai rajouté dans le template {{ form.pseudo.errors }} idem. Je te joins mon html avec le form.py. Je n'arrive toujours pas à voir à coté de quoi je passe... :s

Dans la console de pycharm j'ai bien l'error$ ou le dictionnaire qui remonte toujours...

console pycharm

[17/Sep/2023 13:04:28] "GET / HTTP/1.1" 200 1109
erreur$
[17/Sep/2023 13:04:40] "POST / HTTP/1.1" 200 1109
{'pseudo': 'yann', 'email': '[email protected]', 'password': '12345678', 'job': 'python', 'cgu_accept': True}
[17/Sep/2023 13:05:16] "POST / HTTP/1.1" 200 1113
erreur$
[17/Sep/2023 13:11:53] "POST / HTTP/1.1" 200 1113

index.html

<!DOCTYPE html>

<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Formulaire</title>
</head>
<body>
<h1>Créer un compte</h1>
<form method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value="s'inscrire"/>
</form>
    {{ form.pseudo.errors }}

</body>
</html>

forms.py :

from django import forms


JOBS = (
    ("python", "Developpeur Python"),
    ("javascript", "Developpeur Javascript"),
    ("csharp", "Developpeur C#"),
)

class SignupForm(forms.Form):
    pseudo = forms.CharField(max_length=8, required=False)
    email = forms.EmailField()
    password = forms.CharField(min_length=6)
    job = forms.ChoiceField(choices=JOBS)
    cgu_accept = forms.BooleanField(initial=True)
#form.is_valid() revoi un booleen si valid ou non

    def clean_pseudo(self):
        pseudo = self.cleaned_data.get("pseudo")
        if "$" in pseudo:
            print("erreur$")
            raise forms.ValidationError("Le message ne peut contenir $")
        return pseudo

Merci d'avance pour ton aide.

Yann

Salut Yann,

ah mince.
Il me semble que la méthode is_valid() est celle qui déclenche la vérification des champs et génère le dictionnaire des erreurs.

Est-ce que tu as quelque chose comme ça dans ta vue ?

def ta_vue(request):
    if request.method == "POST":
        form = SignupForm(request.POST)
        if form.is_valid(): 
            // Ton code pour quand le formulaire est valide.
        else:
            // Le formulaire n'est pas valide, renvoie-le au template.
            return render(request, "ton_template.html", {"form": form})
    else:
        form = SignupForm() 
    return render(request, "ton_template.html", {"form": form})

ah aussi. c'est normal que ton {{ form.pseudo.errors }} soit a l'exterieur de ta form ? Il me semble aussi qu'il faut que les message soient envoyé dans une méthode POST or là il n'est pas dans une méthode POST.

Fais un check de ces deux points et tiens-nous au courant si ça résout ton problème !

A+

Problème résolue, j'ai adapté ton code et cela a fonctionné. Voici ce que j'avais dans ma vue :

def signup(request):
    form =SignupForm(request.POST)
    if form.is_valid():
        print(form.cleaned_data)

    form = SignupForm()

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

Est-ce que c'est la condition request.method qui a fait la différence ?

Dans tous les cas merci beaucoup ^^

Thibault houdon

Mentor

Hello Yann,

Yes, c'est exactement ça ! Quand tu soumets un formulaire, ça envoie une requête POST avec les données du formulaire. Dans ton code précédent, tu créais un nouveau formulaire à chaque fois, donc même si le formulaire précédent avait des erreurs, tu perdais ces informations parce que tu en recréais un nouveau juste après.

Maintenant, avec la condition request.method == "POST", tu ne crées un nouveau formulaire que lorsqu'il n'y a pas de requête POST (ou de données de formulaire à vérifier). Sinon, tu réutilises le même formulaire que tu viens de vérifier, donc tu gardes les erreurs à afficher :)

Génial, tout est limpide !

Merci !

Inscris-toi

(c'est gratuit !)

Inscris-toi

Tu dois créer un compte pour participer aux discussions.

Créer un compte

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.