How to check if Django ValidationError subclass was raised?

539 Views Asked by At

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?

2

There are 2 best solutions below

0
JoseKilo On BEST ANSWER

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.

0
ilyasbbu On

Another approach when using except Exception as e::

try:
   ...
except Exception as e:
   if isinstance(e, ValidationError):
       print("Validation error occured")

Nb: This is a general answer to do something when a particular type of error is raised