﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33142	Form clean method called after validation field clean method fails	David Babalola	nobody	"I am working on a Django project wherein the validation depends on the field `clean` method being run first.
According to 
[https://docs.djangoproject.com/en/3.2/ref/forms/validation/#validating-fields-with-clean], each of the fields clean method are called first, then the form's `clean` method is called.

I found out that after a field's clean method is called, and validation fails, that field's `clean` method returns an empty/None value for that field. In essence, it still calls the form's `clean` method after the validation in any of the field fails.
The validation in the form's `clean` method is dependent on the values from those fields. If those values are `None`, or empty my validation would produce an error.

To reproduce this, you can create a form such as this.

{{{
class ActionForm(forms.ModelForm):
    phone_number = forms.CharField(required=False)
    code = forms.CharField(max_length=10, required=False)
    name = forms.CharField(max_length=100)
    
    class Meta:
        model = Withdrawal
        fields = ['name', 'code', 'phone_number']
    
    def clean(self):
        # Ensure you can't withdraw more than your balance
        cleaned_data = super().clean()
        phone_number = cleaned_data.get(""phone_number"")
        code = cleaned_data.get(""code"")
        
        if phone_number == '' and code == '':            
            # Both code and phone number fields are empty: Raise Validation error
            raise forms.ValidationError(""You must enter either the Phone number or the code."")      
        
        user = None        
        
        if phone_number == '' or phone_number is None: 
            # Use user code to get user object
            user = User.objects.get(code=code)
        else:
            # Use user phone number to get user object
            user = User.objects.get(phone_number=phone_number)
        

    def clean_phone_number(self):
        # Check if User with phone number exists
        phone_number = self.cleaned_data.get('phone_number')
        
        if phone_number == '':
            # If User phone number is empty, don't validate it
            return phone_number
        user = User.objects.filter(phone_number=phone_number)        
        if not user.exists():
            raise forms.ValidationError('User with this Phone Number does not exist.')                    
        return phone_number
    
    def clean_code(self):
        # Check if user with user code exists
        code = self.cleaned_data.get('code')       
        if code == '':
            # If User code is empty, don't validate it
            return code                
        user = User.objects.filter(code=code)                
        if not user.exists():
            raise forms.ValidationError('User with this user code does not exist.')                            
        return code
}}}

In the above code, if a code or phone number is entered that is not in the database, the lines `user = User.objects.get(code=code)` and `user = User.objects.get(phone_number=phone_number)` would generate the following error: 
`accounts.models.User.DoesNotExist: User matching query does not exist.`
Furthermore, I printed out the value of the code and phone_number inside the form's `clean()` method. I found out that when invalid values are entered, it prints out empty strings or None. Hence my conclusion that Django calls the form's `clean()` method even after validation of a specific field fails.
"	Bug	closed	Forms	3.2	Normal	invalid			Unreviewed	0	0	0	0	0	0
