如何为 Django 模型字段添加检查约束?
在子类化db.models.Model
时,有时有必要添加额外的检查/约束。
例如,我有一个带有 start_date
和 end_date
的 Event
模型:我想在字段或模型中添加验证,以便 结束日期>开始日期
。
至少我知道这可以在 ModelForm
验证内的 models.Model
之外完成。但是如何附加到字段和 models.Model 呢?
While subclassing db.models.Model
, sometimes it's essential to add extra checks/constraints.
For example, I have an Event
model with start_date
and end_date
: I want to add validation into the fields or the model so that end_date > start_date
.
At least I know this can be done outside the models.Model
inside the ModelForm
validation. But how to attach to the fields and the models.Model
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
从 Django 2.2 开始,数据库级别
支持约束
:As of Django 2.2, database level
constraints
are supported:我不会在 save 方法中添加这样的约束,为时已晚。在那里引发异常,对以错误方式输入数据的用户没有帮助,因为它最终会变成 500,并且用户不会收到有错误的表单等。
您应该在Forms/ModelForms clean 方法并引发 ValidationError,因此
form.is_valid()
返回 false,您可以将表单中的错误发送回用户进行更正。另请注意,自版本 1.2 以来,Django 具有 模型验证 。
它看起来像这样:
I would not put constraints like these in the save method, it's too late. Raising an exception there, doesn't help the user who entered the data in the wrong way, because it will end up as a 500 and the user won't get the form with errors back etc.
You should really check for this in the Forms/ModelForms clean method and raise a ValidationError, so
form.is_valid()
returns false and you can send the errors in the form back to the user for correction.Also note that since version 1.2, Django has had Model Validation.
It would look something like this:
在模型的 save 方法中执行此操作:
Do it inside your save method of your model:
正如 @stefanw 所说,签入表单的 clean 方法会带来更好的用户体验。
如果您非常确定不存在且永远不会存在另一种更改该值的方法,那么这就足够了。但由于您很少能确定这一点,如果数据库一致性很重要,您可以添加另一个检查(除了表单之外),其中之一:
要“完全”确保数据库一致,您可以添加数据库级别约束。例如,您可以使用 RunSQL 和 SQL 等创建迁移像(未测试):
(未测试)。这可能依赖于数据库,这当然是一个缺点。
在您的示例中,这可能不值得(不正确的开始/结束时间看起来有点奇怪,但只影响一个不一致的事件),并且您不希望手动更改架构。但在一致性至关重要的情况下它很有用。
编辑:您还可以只保存开始时间和持续时间,而不是开始和结束时间。
As @stefanw says, it's better user experience to check in the form's clean method.
This is enough if you're very sure that there isn't, and never will be, another way to change the value. But since you can rarely be sure of that, if database consistency is important, you can add another check (in addition to the form), one of:
To be 'completely' sure the database is consistent, you can add a database level constraint. E.g. you can create a migration with RunSQL and SQL, something like (not tested):
(Not tested). This may be database dependent, which is a downside of course.
In your example, it's probably not worth it (incorrect start/end times just look a bit weird, but affect only the one inconsistent event), and you don't want manual schema changes. But it's useful in cases where consistency is critical.
EDIT: You can also just save the start time and the duration, instead of the start and end times.
截至今天,postgres 9.4 和 MS SQL Server >= 2008 支持检查约束在 SQL 中。除此之外,还有 django issues 11964 似乎从昨天开始就已经准备好接受审查,所以希望我们能看到它集成到 django 2 中。该项目 rapilabs/django-db-constraints< /a> 似乎也实现了这一点。
As of today, both postgres 9.4 and MS SQL Server >= 2008 support check constraints in sql. On top of this, there is django issue 11964 which seems to be ready for review since yesterday, so hopefully we'll see this integrated into django 2. The project rapilabs/django-db-constraints seems to implement this too.
总结之前的答案,这是我在项目中使用的完整解决方案:
太糟糕了,没有 django.core.validators 可以处理这个:(
Summarizing the answers from before, here is a complete solution I used for a project:
Too bad there is no
django.core.validators
that can handle this :(