pythondjangopython-2.7django-1.6

How to check if Django ValidationError subclass was raised?


Let's assume I have a Django model:

class MyDjangoModel(models.Model):
    name = models.CharField(max_length=200)
    attribute = models.IntegerField()

    class CustomValidationError(ValidationError):
        pass

    def clean(self):
        if self.attribute < 1:
            raise CustomValidationError("Attribute should be > 1!")

        if len(self.name) > 20:
            raise ValidationError("Name too long!")

I would like to create model instance and validate it:

inst = MyDjangoModel(name="Foo", attribute=0)
try:
    inst.full_clean()
except CustomValidationError:
    print("Hello!")
except ValidationError:
    print("Bye!")

But the code above will never print "Hello!" because full_clean method is raising only ValidationError.

Can anyone suggest, how to call full_clean and check if ValidationError subclass exception was raised?


Solution

  • The full_clean method collects all the errors raised on several phases.

    You can check how it's calling your clean method here: https://github.com/django/django/blob/master/django/db/models/base.py#L1150

    Luckily, the original exceptions are preserved inside error_dict.

    You can try this:

    inst = MyDjangoModel(name="Foo", attribute=0)
    try:
        inst.full_clean()
    except ValidationError as exc:
        for original_exc in exc.error_dict['__all__']:
            if isinstance(original_exc, MyDjangoModel.CustomValidationError):
                print("Hello!")
            elif isinstance(original_exc, ValidationError):
                print("Bye!")
    

    Assuming that CustomValidationError is only raised from the clean method. Otherwise you would also need to check other keys in error_dict.

    Note that the order of the ifs is important: the second one would also be True if the first one is True.