Let `BaseForm._clean_fields` accept a `field` argument for partial fields validation

I’ve had the case, multiple times these last month were I wanted to validate only some form fields and then modify the form before validating the rest of the form. I had some very complex situations but the simplest one is were some fields are required only if the user ticks a checkbox.

Now I know I can leave these fields as not required then verify the data myself in BaseForm.clean but this is just code repetition since requirement check is already done in BaseForm._clean_fields.

What I propose is to modify BaseForm._clean_fields like this:

    def _clean_fields(self, fields=None):
        fields = fields or self._bound_items()
        for name, bf in fields:
            field = bf.field
            value = bf.initial if field.disabled else bf.data
            try:
                if isinstance(field, FileField):
                    value = field.clean(value, bf.initial)
                else:
                    value = field.clean(value)
                self.cleaned_data[name] = value
                if hasattr(self, "clean_%s" % name):
                    value = getattr(self, "clean_%s" % name)()
                    self.cleaned_data[name] = value
            except ValidationError as e:
                self.add_error(name, e)

so that I can validate my form like this:

    def _clean_fields(self, fields=None):
        super()._clean_fields(fields=(...))
        # Change fields requirements or autocomplete form data 
        # with DB data
        super()._clean_fields(fields=(...)) # clean rest of the fields.

Even better: _clean_fields could be part of the public API:

class BaseForm(RenderableFormMixin):
    def clean_field(self, name):
        bf = self[name]
        field = bf.field
        value = bf.initial if field.disabled else bf.data
        try:
            if isinstance(field, FileField):
                value = field.clean(value, bf.initial)
            else:
                value = field.clean(value)
            self.cleaned_data[name] = value
            if hasattr(self, "clean_%s" % name):
                value = getattr(self, "clean_%s" % name)()
                self.cleaned_data[name] = value
        except ValidationError as e:
            self.add_error(name, e)

    def clean_fields(self):
        for name in self.fields:
            self.clean_field(name)

    def _clean_fields(self):
        self.clean_fields()

Here _clean_fields is kept for retro-compatibility.