【问题标题】:How to check if Django ValidationError subclass was raised?如何检查是否提出了 Django ValidationError 子类?
【发布时间】:2026-01-08 04:40:02
【问题描述】:

假设我有一个 Django 模型:

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!")

我想创建模型实例并对其进行验证:

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

但上面的代码永远不会打印"Hello!",因为full_clean 方法只会引发ValidationError

谁能建议,如何调用full_clean 并检查是否引发了ValidationError 子类异常?

【问题讨论】:

  • 一个简单的except ValidationError 也将处理子类的所有实例。
  • @schwobaseggl 是的,谢谢,但我想在引发 ValidationError 的子类时添加自定义逻辑。
  • 底层异常被收集在full_clean 中并且仍然可以访问。查看答案。

标签: python django python-2.7 django-1.6


【解决方案1】:

full_clean 方法收集在几个阶段引发的所有错误。

您可以在此处查看它是如何调用您的 clean 方法的:https://github.com/django/django/blob/master/django/db/models/base.py#L1150

幸运的是,原始异常保存在 error_dict 中。

你可以试试这个:

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!")

假设 CustomValidationError 仅从 clean 方法引发。否则,您还需要检查error_dict 中的其他键。

注意ifs 的顺序很重要:如果第一个是 True,那么第二个也是 True。

【讨论】: