Django 模型验证

Posted

技术标签:

【中文标题】Django 模型验证【英文标题】:Django model validation 【发布时间】:2017-08-16 02:49:04 【问题描述】:

我遇到了验证问题。 我需要同时使用表单验证和模型验证,但是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 添加更多模型验证。

问题是在字段 fk 中没有任何数据的情况下调用 MyModel.clean() 将引发 RelatedObjectDoesNotExist 异常。

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

我可以将 MyModel.clean 操作嵌入到 try/except 中,这会捕获 RealtedObjectDoesNotExist,但它对我来说具有不好的代码味道。 MyModel.fk 存在这一事实应通过第一个表单层验证来确保。

【问题讨论】:

【参考方案1】:

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

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

与其捕获异常,不如在访问self.fk 之前检查self.fk_id 不是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")

【讨论】:

以上是关于Django 模型验证的主要内容,如果未能解决你的问题,请参考以下文章

Django 模型条件验证

没有用户模型的 Django 基于令牌的身份验证

Django 验证

可以在 django 模型验证器中使用多个值吗?

相关领域的 Django 模型验证

根据另一个字段的值验证 Django 模型字段?