Résolue

AtributeError avec un AuthenticationForm

# Héritage # Django # Formulaires

Bonjour,

J'essaie de faire la même chose avec un formulaire qui hérite de AuthenticationForm

Voici le code de ma vue:

def login_user(request):
    if request.method == "POST":
        form = UserLoginForm(request.POST) # formulaire qui hérite de AuthenticationForm
        form.clean() # -> L'erreur est déclenchée par l'appel de cette methode
        user = form.get_user()
        if user:
            login(user)
            return redirect("index")

    form = UserLoginForm()
    return render(request, 'accounts/login.html', context={'form': form})

et voici le traceback:

Traceback (most recent call last):
  File "C:\Users\chris\docstring\django\projets\DocShop\.env\Lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\chris\docstring\django\projets\DocShop\.env\Lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\chris\docstring\django\projets\DocShop\src\accounts\views.py", line 24, in login_user
    form.clean()
  File "C:\Users\chris\docstring\django\projets\DocShop\.env\Lib\site-packages\django\contrib\auth\forms.py", line 198, in clean
    username = self.cleaned_data.get('username')

Exception Type: AttributeError at /accounts/login/
Exception Value: 'UserLoginForm' object has no attribute 'cleaned_data'

je comprend pas, parce que cleaned data est hérité de BaseForm ...

Thibault houdon

Mentor

Bonjour Christian,


Le problème ici n'a pas rapport avec la classe du formulaire utilisé mais la façon dont on doit valider un formulaire (peu importe le formulaire).


Pour avoir accès au dictionnaire cleaned_data il faut déjà vérifier que le formulaire est valide, avec la méthode is_valid.


Si le formulaire est valide, le dictionnaire cleaned_data associé au formulaire est rempli avec les données valides du formulaires.


La méthode clean est appelé par is_valid et peut être surchargée dans le cas où vous souhaiteriez modifier la vérification du champ d'un formulaire.


Vous pouvez voir le processus détaillé dans la documentation :

https://docs.djangoproject.com/fr/4.1/ref/forms/validation/#form-and-field-validation


Dans votre cas il faudrait plutôt faire :


form = UserLoginForm(request.POST)
if form.is_valid():
    username = form.cleaned_data["username"]
    password = form.cleaned_data["password"]
    user = authenticate(username=username, password=password)
    login(request, user)

J'ai éssayé ça :

if form.is_valid():
    print(form.cleaned_data)
    form.clean()
    user = form.get_user()
    if user:
        login(user)
        return redirect("index")
else:
    print(form.data)

le problème c'est que je ne rentre pas dans la condition, pourtant je rentre bien un username et un password

ça me print ça:

<MultiValueDict: {}>


Thibault houdon

Mentor

Il doit y avoir des erreurs alors, tu peux les afficher dans le else avec :

print(form.errors)

non, le print est vide

Et quand tu affiches le request.POST tu vois bien les données du formulaires ?


Aussi si tu as l'occasion de mettre ton projet sur ton Drive je pourrai regarder plus en détail :)

Dans le request.POST il affiche bien le csrfmiddlewaretoken, le username et le password ... je comprend pas

Je met le projet sur mon drive tout de suite, merci !

Bonsoir Christian,


Après pas mal d'essais et de recherches je viens finalement de trouver le problème. Le formulaire AuthenticationForm est effectivement différents des autres formulaires. Le premier argument n'est en effet pas data, celui qui récupère les données de request.POST, mais la requête, ceci pour la gestion des cookies (https://www.janosgyerik.com/django-authenticationform-gotchas/).


Il faut donc initialiser ce formulaire ainsi :

form = UserLoginForm(data=request.POST)


Au lieu de juste :

form = UserLoginForm(request.POST)


On voit en effet la différence dans la méthode init entre le formulaire de base (BaseForm) qui définit data en premier paramètre :


Et AuthenticationForm qui redéfinie la méthode __init__ avec request en premier.


Voilà donc le fin mot de l'histoire ;)


Bonne continuation :) !

Merci ! Effectivement ça marche nickel en passant la requete !

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.