为什么 django 的 model.save() 不调用 full_clean() ?
我只是好奇是否有人知道 Django 的 ORM 不在模型上调用 full_clean 是否有充分的理由,除非它被保存为模型表单的一部分?
请注意,当您调用模型的
save()
方法时,不会自动调用full_clean()
。当您想要为自己手动创建的模型运行一步模型验证时,您需要手动调用它。
- 来自 Django 的full_clean
文档
(注意:更新了 Django 1.6 的引用...之前的 Django 文档也对 ModelForms
提出了警告。)
人们不希望这种行为有充分的理由吗?我认为如果您花时间向模型添加验证,您会希望每次保存模型时都运行验证。
我知道如何让一切正常工作,我只是在寻找解释。
I'm just curious if anyone knows if there's good reason why Django's ORM doesn't call full_clean
on a model unless it is being saved as part of a model form?
Note that
full_clean()
will not be called automatically when you call your model’ssave()
method. You’ll need to call it manually when you want to run one-step model validation for your own manually created models.
- from Django'sfull_clean
doc
(NOTE: quote updated for Django 1.6... previous Django docs had a caveat about ModelForms
as well.)
Are there good reasons why people wouldn't want this behavior? I'd think if you took the time to add validation to a model, you'd want that validation run every time the model is saved.
I know how to get everything to work properly, I'm just looking for an explanation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
AFAIK,这是因为向后兼容性。带有排除字段的 ModelForms、带有默认值的模型、pre_save() 信号等也存在问题。
您可能感兴趣的来源:
AFAIK, this is because of backwards compatibility. There are also problems with
ModelForms
with excluded fields, models with default values,pre_save()
signals, etc.Sources you might be intrested in:
由于兼容性考虑,django 内核中未启用保存时自动清理功能。
如果我们正在开始一个新项目并希望模型上的默认
save
方法可以自动清理,我们可以在保存每个模型之前使用以下信号进行清理。Because of the compatibility considering, the auto clean on save is not enabled in django kernel.
If we are starting a new project and want the default
save
method on Model could clean automatically, we can use the following signal to do clean before every model was saved.调用
full_clean
方法的最简单方法就是重写模型中的save
方法:The simplest way to call the
full_clean
method is just to override thesave
method in your model:评论@Alfred Huang 的回答和评论。人们可以通过在当前模块(models.py)中定义类列表并在 pre_save 挂钩中检查它来将 pre_save 挂钩锁定到应用程序:
Commenting on @Alfred Huang's answer and coments on it. One might lock the pre_save hook down to an app by defining a list of classes in the current module (models.py) and checking against it in the pre_save hook:
如果您希望始终确保模型验证,则全局
pre_save
信号可以很好地发挥作用。但是,它会在当前版本 (3.1.x) 中遇到 Django 身份验证问题,并可能导致您正在使用的其他应用程序的模型出现问题。详细说明@Peter Shannon的答案,这个版本只会验证您执行它的模块内的模型,跳过验证 "raw" 保存 并将
dispatch_uid
添加到 避免重复信号。A global
pre_save
signal can work well if you want to always ensure model validation. However it will run into issues with Django's auth in current versions (3.1.x) and could cause issues with models from other apps you are using.Elaborating on @Peter Shannon's answer, this version will only validate models inside the module you execute it in, skips validation with "raw" saves and adds a
dispatch_uid
to avoid duplicate signals.如果您想要确保一个模型至少具有一个 FK 关系,并且您不想使用
null=False
因为这需要设置默认 FK(这将是垃圾数据),我想出的最好方法是添加自定义.clean()
和.save()
方法。.clean()
引发验证错误,.save()
调用 clean。这样,从表单和其他调用代码、命令行和测试中都可以强制执行完整性。如果没有这个,(AFAICT)就无法编写一个测试来确保模型与专门选择的(非默认)其他模型具有 FK 关系。If you have a model that you want to ensure has at least one FK relationship, and you don't want to use
null=False
because that requires setting a default FK (which would be garbage data), the best way I've come up with is to add custom.clean()
and.save()
methods..clean()
raises the validation error, and.save()
calls the clean. This way the integrity is enforced both from forms and from other calling code, the command line, and tests. Without this, there is (AFAICT) no way to write a test that ensures that a model has a FK relation to a specifically chosen (not default) other model.我们可以将应用程序用作
settings.py
中的INSTALLED_APPS
部分,而不是插入一段声明接收器的代码,在此之前,您可能需要安装
django-fullclean
使用 PyPI:Instead of inserting a piece of code that declares a receiver, we can use an app as
INSTALLED_APPS
section insettings.py
Before that, you may need to install
django-fullclean
using PyPI: