第10章:约束¶
previous chapter 引入了向我们的模型添加一些业务逻辑的能力。我们现在可以将按钮链接到业务代码,但是如何防止用户输入错误的数据呢?例如,在我们的房地产模块中,没有什么可以阻止用户设置负的预期价格。
Odoo 提供了两种设置自动验证不变量的方法:Python constraints 和 SQL constraints。
SQL¶
参考:与此主题相关的文档可以在 型号 和 PostgreSQL’s documentation 中找到。
注解
目标:在本节末尾:
金额应该(严格)为正数
属性类型和标签应该有唯一的名称
SQL 对象是通过 Constraint 属性定义的。
简单的例子:
_check_percentage = models.Constraint(
'CHECK(percentage >= 0 AND percentage <= 100)',
'The percentage of an analytic distribution should be between 0 and 100.',
)
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
可以找到一个简单的示例 here。
Exercise
添加 Python 约束。
添加约束,使销售价格不能低于预期价格的 90%。
提示:在报价得到验证之前,售价为零。您需要微调您的支票以考虑到这一点。
警告
使用浮点数时,请始终使用 odoo.tools.float_utils 中的 float_compare() 和 float_is_zero() 方法!
确保每次销售价格或预期价格发生变化时都会触发约束!
SQL 约束通常比 Python 约束更有效。当性能很重要时,始终优先选择 SQL 而不是 Python 约束。
我们的房地产模块开始看起来不错。我们添加了一些业务逻辑,现在我们确保数据是一致的。然而,用户界面仍然有点粗糙。让我们看看如何在 next chapter 中改进它。