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