如何在优雅地保存在 Django 1.5 之前使用 full_clean() 进行数据验证?

Posted

技术标签:

【中文标题】如何在优雅地保存在 Django 1.5 之前使用 full_clean() 进行数据验证?【英文标题】:How to use full_clean() for data validation before saving in Django 1.5 gracefully? 【发布时间】:2014-04-30 11:43:25 【问题描述】:

我认为Django的模型验证对于那些不使用内置ModelForm的模型来说有点不方便,虽然不知道为什么。

首先full_clean()需要手动调用。

注意full_clean()在你调用的时候不会自动调用 您的模型的 save() 方法,也不是 ModelForm 验证的结果。在 ModelForm验证的情况,Model.clean_fields(),Model.clean(), 和 Model.validate_unique() 都是单独调用的。你需要 当你想运行一步模型时手动调用 full_clean 验证您自己手动创建的模型。

其次,validators用于内置ModelForm

请注意,当您保存 模型,但如果您使用的是 ModelForm,它将运行您的验证器 在表单中包含的任何字段上。

当您需要在将数据保存到数据库之前进行数据验证时,需求量很大。显然我更喜欢在模型中制作它,而不是视图。那么,有什么好的想法可以在 Django 1.5 中优雅地实现这一点吗?

【问题讨论】:

在保存模型之前调用full_clean() 有什么复杂之处? 【参考方案1】:

尽管在模型级别强制验证的想法似乎是正确的,但由于各种原因,Django 在默认情况下不会这样做。除了一些向后兼容性问题外,作者可能不想支持这一点,因为他们担心这会产生一种错误的安全感,而事实上您的数据并不能保证总是得到验证。某些 ORM 方法(例如 bulk_createupdate)不调用 save(),因此无法验证您的模型。 换句话说,很难保证验证,因此他们决定不假装它。

如果您需要为多个模型使用此功能,您可以创建一个简单的 mixin,覆盖 save() 方法并在 super 之前调用 full_clean()。请注意,在某些情况下,这可能会导致验证运行两次,例如在使用 ModelForm 时。如果您的验证例程无副作用且运行成本低廉,这可能不是问题。

有关更多信息,请参阅以下答案:

https://***.com/a/4441740/2263517 https://***.com/a/12945692/2263517 https://***.com/a/13039057/2263517

【讨论】:

所以不鼓励模型级验证,同时不支持数据库中的CHECK约束。如果我不编写网络表单,则没有明确的解决方案。 我会说相反的 - 实际上是鼓励的,只是默认情况下不支持(由于历史原因)。不过,很容易在您的项目中将其设为默认值 - 只需创建一个 mixin 或一个新的模型基类,覆盖 save 方法并在内部调用 full_clean 我已经完成了 .save/full_clean() 路线。问题是 django 查询集提供了多个完全绕过模型验证的默认函数(查询集上的 .update 和其他一些)所以你必须对模型验证函数应该如何被调用、何时以及关于根本不使用哪些数据库更新方法。因此,您可以花费大量时间编写所有模型验证代码,对其进行彻底测试,但您仍然很容易以不一致的方式结束。 是的,这就是为什么它不包含在原始 Django 实现中的原因之一 - 以防止错误的安全感。您必须始终牢记您通常操作对象的所有方式,如果这些方式可能使它们无效。有时,严格的设计决策会有所帮助;也就是说,如果您绝对需要确保对象的有效性,您只能通过 save() 方法操作此类对象,并远离像 .update() 这样的批量操作。

以上是关于如何在优雅地保存在 Django 1.5 之前使用 full_clean() 进行数据验证?的主要内容,如果未能解决你的问题,请参考以下文章

将 ImageView 准确地保存在 XML 位置

Django 1.5 - 使用新的 StreamingHttpResponse

Django 1.5 - 使用新的 StreamingHttpResponse

我应该将令牌安全地保存在内存还是 sqlite 中?或请建议

如何优雅地检查对象/实例/变量的存在,如果它存在于python中,同时将其分配给变量?

如何优雅地重启 django 在 nginx 后面运行 fcgi?