Skip to content

13. 约束的应用

这节将学习如何把按钮与业务代码关联起来,以及如何防止用户输入错误的数据。例如,在estate模块中,还没有任何机制阻止用户输入负数值的价格。

在 Odoo 中,提供了两种设置自动验证变量值的两种方法:Python 约束和 SQL 约束。

SQL约束

在本节中,将学习如何防止用户输入错误的数据,比如价格数值应为正数值。

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

SQL 对象是通过约束属性定义的。简单示例如下:

python
_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 约束。此时可能会弹出类似以下的错误信息:

shell
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() 装饰器装饰的方法,并在记录集上调用。该装饰器指定了参与约束的字段。当这些字段中的任何一个被修改时,约束会自动进行计算评估。如果该方法的不变量未得到满足,则按设定预期抛出异常:

python
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%;
python
    # 数据库唯一约束(Odoo 19中已弃用)
    #_sql_constraints = [
    #    ('unique_name', 'unique(name)', 'The name already created'),
    #]
    
    #  数据库唯一约束(Odoo 19中定义唯一键的方式)
    _unique_name = models.Constraint(
        'UNIQUE(name)',
        '名称必须唯一',
    )

经过前面不断的完善,estate模块初具雏形。在本节教程中添加了一些业务逻辑,并确保了数据的一致性。

最近更新