How can I stop from validation process when reCaptcha failed?

I have a Form like below:

from django import forms
from captcha.fields import ReCaptchaField
from captcha.widgets import ReCaptchaV2Checkbox
from .models import User

class DummyForm(forms.Form):
    email = forms.EmailField()
    captcha = ReCaptchaField(widget = ReCaptchaV2Checkbox())

    def clean_email(self):
        try:
            User.objects.get(email=self.cleaned_data['email'])
            raise forms.ValidationError('This email has already existed')
        except User.DoesNotExist:
            return self.cleaned_data['email']

I want to stop the validation process when the captcha raises ValidationError.
I’ve tried this code below but it didn’t work.

    def clean(self):
        # if the captcha is invalid it returns True and this line of code works very well.
       # but the logic that I want doesn't work and it tries to clean_email and I don't want it to do it.
        if self.has_error('captcha'):
            return

The clean method on a form is called after all the field clean methods have been called. (See the docs at Form and field validation | Django documentation | Django to understand the sequence in which the form validation steps occur.)

If you want to prevent the validation from being run on those two fields, you’re probably going to want to override full_clean for the form to call the validate method on the captcha field before allowing it to perform its regular functions. (I’m not sure how well that’s going to work - I’d have my concerns about handling it this way.)

What I would actually recommend (and what I have done in the past) is to allow Django to perform the full validation, and then check the errors that are returned. If the captcha error is included in the errors, then take a different action. (That work is done in the view.)

1 Like

Because for example clean_email method hits the database I want to first validate the captcha and if it isn’t invalid then perform full validation on other fields.
I found this but I am looking for another way to handle this logic completely on Form and not on View.

I think you’re applying constraints that really aren’t (shouldn’t) be an issue. You could waste a lot of time trying to work around non-problems, or you could fix the issue and move on - possibly revisiting it if down the road it becomes an issue.

1 Like