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