Django:停止在 ValidationError 上创建模型实例

Django: Stop model instance creation on ValidationError

我已经定义了一个模型并自定义了 clean() 方法以进行更好的验证。如果我在前端使用该模型,它就可以工作,并且我无法保存不符合我的验证标准的模型。 但是当我通过 shell 保存或编写我的测试时,仍然会保存一个错误的模型。

models.py

class FooModel(models.Model):
    weight_min = models.DecimalField(default=40.0, max_digits=4, decimal_places=1)
    weight_max = models.DecimalField(default=40.0, max_digits=4, decimal_places=1)

    def clean(self):
        if self.weight_min > self.weight_max:
             raise ValidationError("'Weight min' must be smaller than 'Weight max'.")

tests.py

def test_create_model_with_wrong_weight(self):
        foo = FooModel(weight_min=40.0, weight_max=30.0)

        self.assertRaises(ValidationError, match.save()) # Works, but still saves the model 
        self.assertIs(0, Match.objects.all()) # Fails, QuerySet has objects.

我阅读了文档并尝试在 save() 中调用 full_clean() 但后来我不知道如何编写测试。

我需要做什么才能:

save 方法不应该进行验证,它不是设计使然,因此您甚至可以保存无效的模型实例。

您的工作流程可能如下所示:

try:
    match.full_clean()
    match.save()
except ValidationError as e:
    # Do something based on the errors contained in e.message_dict.
    # Display them to a user, or handle them programmatically.

https://docs.djangoproject.com/en/2.0/ref/models/instances/#validating-objects

向模型的 .save() 方法添加验证(即 .full_clean() 调用)通常不是一个好主意,因为如果您稍后通过表单使用该模型,.full_clean() 将被调用两次(通过表单,通过 .save() 方法),但如果你不介意这个,你可以像下面这样:

class Match:
    ...
    def save(self, *args, **kwargs):
        try:
            self.full_clean()
            super().save(*args, **kwargs)  # actually save the valid match
        except ValidationError as e:
            ...  # work with e.message_dict etc.