如何在优雅地保存在 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_create
或 update
)不调用 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() 进行数据验证?的主要内容,如果未能解决你的问题,请参考以下文章
Django 1.5 - 使用新的 StreamingHttpResponse
Django 1.5 - 使用新的 StreamingHttpResponse
我应该将令牌安全地保存在内存还是 sqlite 中?或请建议