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

时间:2018-04-21 10:03:51

标签: django django-models django-testing

我已经定义了一个模型并定制了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.

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

我该怎么做:

  • 提出ValidationError
  • 防止保存错误的模型实例

1 个答案:

答案 0 :(得分:4)

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.