为啥 Django Rest Framework 不鼓励模型级别验证?

Posted

技术标签:

【中文标题】为啥 Django Rest Framework 不鼓励模型级别验证?【英文标题】:Why does Django Rest Framework discourage model level validation?为什么 Django Rest Framework 不鼓励模型级别验证? 【发布时间】:2015-12-26 08:19:00 【问题描述】:

Django Rest Framework 序列化器在验证模型序列化器时不会调用Model.clean。给出的解释是,这会导致“更清晰的关注点分离”,from the Django Rest Framework 3.0 release notes:

ModelSerializer 验证和 ModelForm 的区别。

这一变化也意味着我们不再使用.full_clean() 方法 在模型实例上,而是显式地执行所有验证 序列化器。这提供了更干净的分离,并确保 ModelSerializer 类没有自动验证行为 这也不能在常规的 Serializer 类上轻松复制。

但是 Django Rest Framework 的作者试图分离的关注点是什么?


我的猜测是他们说模型实例不应该关心它自己的有效性。如果是这样,我不明白为什么。

【问题讨论】:

我在这个问题上支持你,当 Django Admin、Django Forms、Shell 等调用 clean 方法时,DRF 不调用它是完全出乎意料的。这是多余的为我们的开发人员工作。 【参考方案1】:

模型的“full_clean”有两个主要问题。 第一个是技术性的。有几种情况根本没有调用 full_clean。例如,当您执行queryset.update() 时,您将绕过它。

第二个问题是,如果您有一个复杂的业务逻辑 - 这通常是您需要 full_clean 的原因 - 您可能应该在业务逻辑中进行验证,而不是深入到模型进行验证。 每一层都应该负责自己的一致性,而存储层(即模型)不应该关心业务层。

我能想到的另一件事是,一旦您拥有一个在序列化程序进行验证之后出现的模型,就会调用 full_clean。此时,事情开始变得混乱,因为您有一个两步验证,其中创建了一个对象。

如果您使用nested serializer,您可能会被困在这里,因为在保存主模型之前您将无法创建嵌套模型,这将使​​完全干净的调用更加混乱 - 将创建一些对象,其他人不会。很难弄清楚应该在什么时候以及什么对象应该用他们的 full_clean 来验证,你可以肯定会有很多来自用户的抱怨,当他们将覆盖更新/清理并找出 full_clean 没有被调用时每个模型。 这开始变得令人头疼,我们更愿意让事情变得更简单、更明确。

【讨论】:

你能更明确地解释一下这部分吗? “第二个问题是,如果您有复杂的业务逻辑 [...],您可能应该在业务逻辑中进行验证,而不是深入模型进行验证。”该业务逻辑将在哪里存在并从哪里调用?你的意思是序列化器应该在验证期间调用一些业务逻辑吗?似乎在这个主题上有many opinions,这对于新的 Django / DRF 用户来说是不直观的。 “该业务逻辑将在哪里存在并从哪里调用?”在 MVC 中,它将在控制器中调用(在 django 中查看)。当您有复杂的逻辑(例如处理实时库存的商店)时,有时最好将库存计算留给业务层并让该层进行自己的验证。然后,序列化程序将只执行基本检查。已经写了一些关于此的想法(dabapps.com/blog/django-models-and-encapsulation)。请注意,这是 DRF 所做的设计选择。 嗨@Linovia - 仅供参考,这是否在 DRF 的文档中突出显示? 不,不是。这是与 Tom 聊天后的解释,以及在问题跟踪器上回答问题时用作指南的内容。

以上是关于为啥 Django Rest Framework 不鼓励模型级别验证?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Django REST Framework 提供不同的身份验证机制

为啥 Django Rest Framework 不鼓励模型级别验证?

为啥我的 Django REST Framework 视图集 URL 没有解析?

Django Rest Framework - 为啥在尝试使用不正确的凭据登录用户时返回 200 状态码?

为啥从 django rest 框架返回的 JSON 在响应中有正斜杠?

Django-rest-framework 和 django-rest-framework-jwt APIViews and validation Authorization headers