web-dev-qa-db-fra.com

django - comment traiter / nettoyer un champ avant la validation

J'ai un formulaire qui ne doit être validé qu'après avoir été nettoyé.

Que se passe-t-il lorsque vous exécutez form.is_valid()? Le formulaire est-il nettoyé, puis cette version nettoyée du formulaire est-elle validée?

Le comportement que j'obtiens en ce moment, c'est que si mon champ ne passe pas la validation avant le nettoyage, même si le nettoyage le ferait passer, is_valid() retourne False.

Est-ce que je fais quelque chose de mal?

Code:

# View
class ContactForm(forms.Form):
    message = forms.CharField(widget=forms.Textarea, max_length=5)

    def clean_message(self):
        message = self.cleaned_data['message']
        return message.replace('a', '') # remove all "a"s from message

def contact(request):
    if request.method == 'POST':
        if form.is_valid():
            return HttpResponseRedirect('/contact/on_success/')
        else:
            return HttpResponseRedirect('/contact/on_failure/')

Je veux que form.is_valid() renvoie True si le message contient moins de 5 caractères PAS y compris a !

Est-il possible d'exécuter clean_<fieldname>() après to_python() mais avant run_validators()? Ou devrais-je faire cela d'une autre manière?

28
Acorn

Je pense que le processus de validation du formulaire (et son ordre correct) est vraiment bien documenté. http://docs.djangoproject.com/en/dev/ref/forms/validation/#form-and-field-validation

Pourriez-vous partager votre code? Il existe une méthode clean sur chaque champ de formulaire, responsable de l'exécution de to_python, validate et run_validators (dans cet ordre). to_python accepte la valeur brute du widget, en la forçant dans un python, validate prend la valeur contrainte et exécute une validation spécifique au champ.

Réponse mise à jour par rapport au code donné

clean_message est appelé après que toutes les autres validations se soient déroulées comme to_python, validate et, surtout, run_validators. Je pense que la dernière méthode vérifiera que le max_length la contrainte n'est pas violée. Donc, vous modifiez les données par la suite n'a aucun effet.

La solution est d'élever un ValidationError ici. Suppression de max_length évitera toute validation de la longueur de l'entrée.

class ContactForm(forms.Form):
    message = forms.CharField(widget=forms.Textarea)

    def clean_message(self):
        message = self.cleaned_data['message']
        message = message.replace('a', '') # remove all "a"s from message
        if len(message) >= 5:
            raise ValidationError('Too many characters ...')
        return message
35
Reiner Gerecke

De plus, lorsque is_valid() retourne False, vous pouvez vérifier pourquoi, en imprimant self.errors À l'intérieur du formulaire.

si vous regardez le code is_valid(), cela vérifie le formulaire is_bound et le self.errors est vide

2
Nicolas Rojo

Vous pouvez remplacer CharField:

class CustomCharField(forms.CharField):
    def clean(self, value):
        return super().clean(value.replace('a', ''))

Ensuite, vous pouvez l'utiliser sous forme

class ContactForm(forms.Form):
    message = CustomCharField(widget=forms.Textarea)
0
Qwarky