我有一个特定的模型,我想对其执行自定义验证。我想保证在创建新实例时始终存在至少一个标识符字段,这样就不可能在没有这些字段之一的情况下创建实例,尽管没有特别需要单独的字段。
from django.db import models
class Security(models.Model):
symbol = models.CharField(unique=True, blank=True)
sedol = models.CharField(unique=True, blank=True)
tradingitemid = models.Charfield(unique=True, blank=True)
我想要一种干净、可靠的方法来执行此操作,无论原始数据来自何处(例如,API 帖子或从其他来源(如 .csv 文件)获取此数据的内部函数)。
我知道我可以覆盖 models .save() 方法并执行验证,但最佳实践已说明here https://stackoverflow.com/questions/8771029/raise-a-validation-error-in-a-models-save-method-in-django建议在 .save() 方法中引发验证错误是一个坏主意,因为视图只会返回 500 响应,而不是向 post 请求返回验证错误。
我知道我可以定义一个自定义序列化器验证器 http://www.django-rest-framework.org/api-guide/validators/使用 Django Rest Framework 来验证数据的模型(这对于创建对象的 ModelViewSet 来说是一个很好的解决方案,我可以保证每次都会使用这个序列化器)。但是,这种数据完整性保证仅在该 API 端点上有效,并且开发人员每次在代码库中的其他位置创建对象时都记得使用该序列化器(对象可以在整个代码库中从除网络 API)。
我也熟悉Django的.clean() 和 .full_clean() 方法 https://docs.djangoproject.com/en/2.0/ref/models/instances/#validating-objects。这些看起来像是完美的解决方案,只不过它再次依赖于开发人员始终记得调用这些方法——这取决于开发人员的记忆力。我知道使用 ModelForm 时会自动调用这些方法,但同样,对于我的用例模型也可以从 .csv 下载创建 - 我需要一个通用的保证,这是最佳实践。我可以将 .clean() 放入模型的 .save() 方法中,但是这个answer https://stackoverflow.com/questions/4441539/why-doesnt-djangos-model-save-call-full-clean(以及帖子中的相关评论和链接)似乎使这种方法引起争议,并且可能是一种反模式。
有没有一种干净、直接的方法来保证这个模型永远不会在没有以下三个字段之一的情况下被保存:1.不会通过视图引发 500 个错误,2.不依赖于开发人员显式使用创建对象时在整个代码库中正确的序列化程序,以及 3. 不依赖于将对 .clean() 的调用侵入到模型的 .save() 方法中(看似反模式)?我觉得这里必须有一个干净的解决方案,它不是将一些验证放入序列化器中的大杂烩,一些验证放在 .clean() 方法中,黑客 .save() 方法来调用 .clean() (它会通过 ModelForms 的保存被调用两次),等等...