Chapter 10: Constraints¶
The previous chapter introduced the ability to add some business logic to our model. We can now link buttons to business code, but how can we prevent users from entering incorrect data? For example, in our real estate module nothing prevents users from setting a negative expected price.
Odoo 提供了两种设置自动验证不变量的方法: Python 约束
和 SQL 约束
。
SQL¶
参考: 有关此主题的文档可以在 模型 和 PostgreSQL 的文档 中找到。
注解
目标:在本节结束时:
金额应该是(严格)正数
属性类型和标签应该有唯一的名称
SQL 约束是通过模型属性 _sql_constraints
定义的。此属性被赋予一个包含字符串 (name, sql_definition, message)
的三元组列表,其中 name
是一个有效的 SQL 约束名, sql_definition
是一个 table_constraint 表达式, message
是错误消息。
您可以在这里找到一个简单的例子 here.
Exercise
添加 SQL 约束。
将以下约束条件添加到相应的模型中:
物业预期价格必须严格为正数
房产销售价格必须为正数
报价必须严格为正数
属性标签名称和属性类型名称必须唯一
提示:在Odoo代码库中搜索 unique
关键字以获取唯一名称的示例。
使用 -u estate
选项重新启动服务器以查看结果。请注意,您可能有数据阻止 SQL 约束的设置。可能会弹出类似以下错误消息的消息框:
ERROR rd-demo odoo.schema: Table 'estate_property_offer': unable to add constraint 'estate_property_offer_check_price' as CHECK(price > 0)
例如,如果某些报价的价格为零,则无法应用约束条件。您可以删除有问题的数据以应用新的约束条件。
Python¶
参考: 有关此主题的文档可以在 constrains()
中找到。
注解
目标:在本节结束时,将不可能接受低于预期价格的90%的报价。
SQL约束是确保数据一致性的有效方法。但是,可能需要进行更复杂的检查,需要使用Python代码。在这种情况下,我们需要一个Python约束。
Python 约束是一个使用 constrains()
装饰的方法,它在记录集上被调用。装饰器指定了哪些字段参与约束。当这些字段中的任何一个被修改时,约束会自动进行评估。如果不满足其不变量,该方法应该引发异常:
from odoo.exceptions import ValidationError
...
@api.constrains('date_end')
def _check_date_end(self):
for record in self:
if record.date_end < fields.Date.today():
raise ValidationError("The end date cannot be set in the past")
# all records passed the test, don't return anything
一个简单的例子可以在 这里 找到。
Exercise
添加 Python 约束。
添加一个约束条件,使得销售价格不能低于预期价格的90%。
提示:在报价被验证之前,销售价格为零。您需要微调您的检查以考虑这一点。
警告
始终在处理浮点数时使用 odoo.tools.float_utils
中的 float_compare()
和 float_is_zero()
方法!
确保每次销售价格或预期价格发生变化时都会触发约束条件!
SQL约束通常比Python约束更有效。当性能很重要时,始终优先选择SQL而不是Python约束。
Our real estate module is starting to look good. We added some business logic, and now we make sure the data is consistent. However, the user interface is still a bit rough. Let’s see how we can improve it in the next chapter.