第 10 章:约束¶
上一章 介绍了为模型添加业务逻辑的能力。现在我们可以将按钮关联到业务代码,但如何防止用户输入不正确的数据呢?例如,在不动产模块中,没有任何东西阻止用户将预期价格设置为负数。
Odoo 提供两种设置自动验证不变量的方式:Python 约束 和 SQL 约束 。
SQL¶
参考资料:与此主题相关的文档可参见 模型 和 PostgreSQL 文档。
Note
目标:在本节结束时:
金额应为(严格)正数
房产类型和标签的名称应唯一
SQL 约束通过模型属性 _sql_constraints 定义。该属性被赋予一个由三元组组成的列表,包含字符串 (name, sql_definition, message),其中 name 是有效的 SQL 约束名,sql_definition 是 table_constraint 表达式,message 是错误消息。
您可以在 此处 找到一个简单的示例。
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()。
Note
目标:在本节结束时,将无法接受低于预期价格 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%。
提示:在报价被验证之前售价为零。您需要细化检查逻辑,将这一点考虑在内。
Warning
处理浮点数时,请始终使用 odoo.tools.float_utils 中的 float_compare() 和 float_is_zero() 方法!
确保每次售价或预期价格发生变化时都会触发该约束!
SQL 约束通常比 Python 约束更高效。当性能很重要时,始终优先选择 SQL 约束而非 Python 约束。
我们的不动产模块开始有模有样了。我们添加了一些业务逻辑,现在还确保了数据的一致性。然而,用户界面仍然有点简陋。让我们在 下一章 中看看如何改进它。