13. 约束的应用
这节将学习如何把按钮与业务代码关联起来,以及如何防止用户输入错误的数据。例如,在estate模块中,还没有任何机制阻止用户输入负数值的价格。
在 Odoo 中,提供了两种设置自动验证变量值的两种方法:Python 约束和 SQL 约束。
SQL约束
在本节中,将学习如何防止用户输入错误的数据,比如价格数值应为正数值。

属性类型和标签应具有唯一的名称:

SQL 对象是通过约束属性定义的。简单示例如下:
_check_percentage = models.Constraint(
'CHECK(percentage >= 0 AND percentage <= 100)',
'The percentage of an analytic distribution should be between 0 and 100.',
)添加 SQL 约束 - 在相应的模型中添加以下约束:
房产的预期价格必须为正数;
房产的售价必须为正数;
报价必须为正数;
房产标签名称和房产类型名称必须唯一;
使用 -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约束
在本节结束时,将实现约束:无法接受低于预期价格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练习:添加 Python 约束条件
添加一个约束条件,确保售价不得低于预期价格的 90%。在验证报价之前,售价为零。需要调整检查逻辑以考虑这一情况。
处理浮点数时,请务必使用
odoo.tools.float_utils包中的float_compare()和float_is_zero()方法。确保每次销售价格或预期价格发生变更时,该约束条件都会被触发。
SQL 约束通常比 Python 约束更高效。当性能变得更重要时,应优先选择 SQL 约束而非 Python 约束。
开发实践
添加 SQL 约束 - 在相应的模型中添加以下约束:
房产的预期价格必须为正数值;
房产的售价必须为正数值;
报价必须为正数值;
房产标签名称和房产类型名称必须唯一;
添加Python约束条件
- 确保售价不得低于预期价格的 90%;
# 数据库唯一约束(Odoo 19中已弃用)
#_sql_constraints = [
# ('unique_name', 'unique(name)', 'The name already created'),
#]
# 数据库唯一约束(Odoo 19中定义唯一键的方式)
_unique_name = models.Constraint(
'UNIQUE(name)',
'名称必须唯一',
)经过前面不断的完善,estate模块初具雏形。在本节教程中添加了一些业务逻辑,并确保了数据的一致性。