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?
# 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/') 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?
The clean_<fieldname>() method is called on a form subclass – where <fieldname> is replaced with the name of the form field attribute. This method does any cleaning that is specific to that particular attribute, unrelated to the type of field that it is. This method is not passed any parameters.
If yes try to disable this behavior, set the novalidate attribute on the form tag As <form action="{% url 'new_page' %}", method="POST" novalidate> in your html file.
to_python() method of the models. Field subclass (obviously for that to work you must write custom fields). Possible use cases: when it is absolutely neccessary to ensure, that an empty string doesn't get written into the database (blank=False keyword argument doesn't work here, it is for form validation only)
The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With