Résolue

Surcharge de la méthode clean Django

# Méthodes # Django

Gabriel Trouvé

Mentor

Bonsoir,

Dans la méthode clean quand je fais :
quantity = self.cleaned_data.get...
Je me suis rendu compte qu'on était pas obligé de mettre le self devant cleaned_data.
J'ai un peu de mal à le comprendre...

Parce que à ma variable cleaned_data j'attribue ma fonction super qui fait partie de clean qui est une méthode d'instance ? Et donc pas besoin de répéter le self ?

Merci d'avance ^^

class OrderForm(forms.ModelForm):
    # je modifie le widget utilisé
    # modifier la qté dans le panier :
    quantity = forms.IntegerField(max_value=100, min_value=1)
    # supprimer un article du panier :
    delete = forms.BooleanField(initial=False, required=False, label='supprimer')

    class Meta:
        model = Order
        fields = ["quantity", 'delete']

    def clean(self):
        cleaned_data = super().clean()
        quantity = self.cleaned_data.get("quantity")
        if quantity > self.instance.ticket.stock:
            raise forms.ValidationError(f"Il ne reste que {self.instance.ticket.stock} tickets en stock")

        return cleaned_data

Gabriel Trouvé

Mentor

Je fais un petit Up ^^

Salut Gabriel,

désolé pour le retard. Tu as bien fait de faire un 'up'.
Je fais un appel à un ami sur celle là =D.

Thibault houdon

Mentor

Salut Gab,

Il y a plein de choses en jeu ici. Le mieux est d'aller lire la documentation qui explique en détail tous les mécanismes de l'implémentation d'une surcharge de la méthode clean :

https://docs.djangoproject.com/fr/4.2/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

La méthode clean va populer ton dictionnaire cleaned_data (celui de l'instance, auquel tu accèdes avec self donc).

Comme indiqué dans la documentation, selon les cas de figure, tu pourras vouloir juste appeler la méthode clean du parent, sans forcément récupérer les informations dans une variable.

Je te laisse aller lire la documentation pour voir si c'est clair pour toi avant de tout reformuler, mais n'hésite pas si tu as encore besoin de précision une fois la lecture effectuée :)

Gabriel Trouvé

Mentor

Je suis désolé Thibault, je ne sais pas pk mais je galère un peu là-dessus.
Utiliser le self ou non, je bloque vraiment avec ça. J'ai lu 3 fois les paragraphes de la doc pourtant.

Tu pourrais m'expliquer avec tes mots à toi ? (j'avoue je me sens con là lol)

Merci d'avance

Salut Gab ! Pas de souci, il y a pas mal de concepts en jeu c'est normal d'être perdu.

Quand tu appelles self.cleaned_data, tu fais référence à l'attribut de l'instance cleaned_data. Mais à ce stade, cleaned_data n'existe pas encore !

C'est la méthode super().clean() qui va se charger de la calculer et la populer dans l'objet cleaned_data :)

Quand tu appelles la méthode sur super() qui se chargera de calculer l'attribut et de populer l'instance avec les données. Donc super().clean() permet de déclencher toute la chaîne de validation, puis tu peux utiliser self.cleaned_data pour accéder aux données validées.

Par rapport à ta question initiale, tu indiquais que de mettre le self ou non ne changeait rien. Dans ton cas c'est parce que tu assignes le résultat de super().clean() à la variable cleaned_data. Or, la méthode clean retourne justement le self.cleaned_data :

def clean(self):
    self._validate_unique = True
    return self.cleaned_data

Du coup dans ce cas précis, que tu utilises ta variable cleaned_data locale que tu définis à la première ligne de la fonction en appelant clean (qui sera donc égale self.cleaned_data) ou directement self.cleaned_data : ça revient au même !

Pour te montrer plus clairement, change le nom de ta variable :

def clean(self):
    patrick = super().clean()
        # Par la suite, tu peux utiliser patrick comme si tu utilisais self.cleaned_data
    quantity = patrick.get("quantity")

Tu peux aussi ne pas assigner super().clean() et juste utiliser self.cleaned_data :

def clean(self):
    # On appelle la méthode clean du parent, qui va populer self.cleaned_data, sans l'assigner car ce n'est pas utile en fait, on peut utiliser directement self.cleaned_data :)
    super().clean()
    quantity = self.cleaned_data.get("quantity")

N'hésite pas si tu as d'autres interrogations par rapport à tout ça, c'est normal :)

Gabriel Trouvé

Mentor

J'ai tout compris !! Après cette explication ça me parait facile à comprendre ! :)

Merci beaucoup Thibault !

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.