开发者

django - how to process/clean a field before validation

I have a form that needs to be validated only after it has been cleaned.

What happens when you run form.is_valid() ? Is the form cleaned and then that cleaned version of the form validated?

The behaviour I'm getting at the moment, is that if my field does not pass validation before cleaning, even if cleaning would make it pass, is_valid() returns False.

Am I doing something wrong?

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/o开发者_如何学Gon_success/')
        else:
            return HttpResponseRedirect('/contact/on_failure/')

I want form.is_valid() to return True if the message has less than 5 characters NOT including a!

Is it possible to run clean_<fieldname>() after to_python() but before run_validators()? Or should I be doing this some other way?


I think the process of form validation (and its correct order) is really well documented.

Would you mind sharing your code? There is a clean method on every formfield, responsible for running to_python, validate and run_validators (in this order). to_python accepts the raw value of the widget, coercing it into a python type, validate takes the coerced value and runs field-specific validation.

Answer updated with regards to the code given

clean_message is called after all the other validation has run like to_python, validate and, most importantly, run_validators. I think the last method will check the that the max_length constraint isn't violated. So you changing the data afterwards has no affect.

The solution is to raise a ValidationError here. Removing max_length will avoid any validation on the input's length.

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


As an extra, when is_valid() return False, you can check why, printing self.errors inside the form.

if you watch the is_valid() code, this checks the form is_bound and the self.errors is empty


You can overwrite CharField:

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

Then you can use it in form

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


Just adding to Reiner Gerecke.

When the is_valid() method is called on the form, the MultiEmailField.clean() method will be run as part of the cleaning process and it will, in turn, call the custom to_python() and validate() methods. Just read the "Form field default cleaning" part and its example

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜