Django模型验证

时间:2017-03-23 13:46:35

标签: django forms validation model

我正面临验证问题。 我需要一起使用表单验证和模型验证,但django(1.10)似乎不喜欢这样。

以下是我的设置的简短版本:

class MyModel(models.Model):
    fk = models.ForeignKey('ap.Model')
    foo = models.CharField(max_length=12)

    def clean(self):
        if self.fk.som_field != self.foo:
            raise ValidationError("This did not validate")

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ('fk',)

def view(request):
    instance = MyModel(foo='bar')
    form = MyModelForm(data=request.POST, instance=instance)
    if form.is_valid():
        # process
        # redirect
    # display template

所以我在模型中有一些模型字段验证。 我在这里需要它,因为它在我的应用程序的其他非表单相关部分中重复使用。

我在表单中有一些用户输入验证。 在这种情况下,检查提供的fk是否有效且存在。

但是当表单经过验证并且用户提供的“fk”无效时,表单将被拒绝。 但是表单也调用MyModel.full_clean添加更多的模型验证。

问题是调用MyModel.clean()而字段 fk 中没有任何数据会引发一个RelatedObjectDoesNotExist异常。

我怎样才能以正确的方式做到这一点? 我觉得MyModel.full_clean()不应该被表单调用,直到表单本身有效,以确保模型中至少使用正确的字段类型进行验证。

我可以在try /中嵌入我的MyModel.clean操作,除了会捕获RealtedObjectDoesNotExist,但它对我来说有一个糟糕的代码味道。 MyModel.fk存在的事实应该通过第一次表单层验证来确保。

1 个答案:

答案 0 :(得分:0)

如您所见,模型表单执行实例验证(通过调用self.instance.full_clean()`)表单是否有效。

您可以阻止此行为(我可能会尝试覆盖_post_clean,但我认为考虑clean方法中的行为更为简单。

在访问self.fk_id之前,检查self.fk是否为None更简单,而不是捕获异常。

class MyModel(models.Model):
    fk = models.ForeignKey('ap.Model')
    foo = models.CharField(max_length=12)

    def clean(self):
        if self.fk_id is not None and self.fk.som_field != self.foo:
            raise ValidationError("This did not validate")