第11章:约束

上一章 中,我们介绍了向模型中添加一些业务逻辑的能力。现在我们可以将按钮链接到业务代码,但是如何防止用户输入不正确的数据呢?例如,在我们的房地产模块中,没有任何东西可以阻止用户设置负的预期价格。

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%的报价。

Python 约束

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约束。

我们的房地产模块看起来不错。我们添加了一些业务逻辑,现在我们确保数据的一致性。然而,用户界面还有点粗糙。让我们看看在 下一章节 中我们如何改进它。