Search code examples
djangodjango-rest-frameworkvalidationerror

Is it possible to merge a Model/Form validator in Django-Rest-Framework?


I've noticed that Django form and model validators should raise a django.core.exceptions.ValidationError, which is an immediate subclass of Exception.

In DRF, however, my validator is expected to raise rest_framework.exceptions.ValidationError, which is not a descendant of Django's (it derives from rest_framework.exceptions.APIException(Exception)).

Keeping myself DRY, how can I write a validator once, and use it in both, say, Django forms and a DRF serializer?

Here is a related question where DRF does not catch a Django core ValidationError


Solution

  • I'm using django==1.8 and DRF==3.3.2 and I've just written custom validator in my project and have noticed that both django.core and restframework's ValidationError exceptions works equally fine in DRF. I think this is due to this code in rest_framework.fields:

    from django.core.exceptions import ValidationError as DjangoValidationError
    from rest_framework.exceptions import ValidationError
    ...
    def run_validators(self, value):
        """
        Test the given value against all the validators on the field,
        and either raise a `ValidationError` or simply return.
        """
        errors = []
        for validator in self.validators:
            if hasattr(validator, 'set_context'):
                validator.set_context(self)
    
            try:
                validator(value)
            except ValidationError as exc:
                # If the validation error contains a mapping of fields to
                # errors then simply raise it immediately rather than
                # attempting to accumulate a list of errors.
                if isinstance(exc.detail, dict):
                    raise
                errors.extend(exc.detail)
            except DjangoValidationError as exc:
                errors.extend(exc.messages)
        if errors:
            raise ValidationError(errors)
    

    As you can see, both exceptions can be caught by DRF, so you can use django.core.exceptions.ValidationError in both django forms and DRF.