第11 章 约束
前面的章节介绍了如何向模型中添加商业逻辑。我们现在可以将按钮链接到商业逻辑,但是我们怎么阻止用户输入不正确的数据呢,比如,在房地产模块中怎么阻止用户输入一个负的售价?
Odoo提供了两种方式自动的确认有效性: Python约束和Sql约束
SQL
参考:关于这个主题的文档在这里 Models and in the PostgreSQL’s documentation.
Note
Goal: at the end of this section:
- 金额必须设置为正数
- 房产类型和标签名称必须唯一
SQL约束通过模型的_sql_constraints属性来定义,这个属性是一个三元组的列表(name, sql_definition, message), 其中
name: 有效的sql约束的名字
sql_definition: 约束表达式
message: 错误信息
You can find a simple example here.
_sql_constraints = [
('check_percentage', 'CHECK(percentage >= 0 AND percentage <= 100)',
'The percentage of an analytic distribution should be between 0 and 100.')
]
练习
增加sql约束
在相应的模型上增加下列约束
- 房产的期望售价必须严格为正数 (>0)
- 房产的售价必须为正数
_sql_constraints = [('price', 'CHECK(expected_price>0 and selling_price>=0)', '报价必须大于0.')
- 报价必须严格为正数
_sql_constraints = [('price', 'CHECK(price>0)', '报价必须大于0.')]
- 房产类型和标签名称必须唯一
_sql_constraints = [('name_unique', 'unique(name)', '名称已经存在.')]
Tip: 可以在Odoo代码中通过搜索unique关键字来查找例子
通过-u estate来重启服务,你可能会看到如下错误
ERROR rd-demo odoo.schema: Table 'estate_property_offer': unable to add constraint 'estate_property_offer_check_price' as CHECK(price > 0)
说明数据库中有些记录不符合约束条件,导致添加约束失败,只要将不符合约束的记录删除再重启服务就ok了。
Python
参考:关于这个主题的文档在这里 constrains()
.
Note
Goal: 在本节结尾,低于期望售价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%
Tip: 售价一直是0知道有报价被接受,你需要微调你的约束
@api.constrains("selling_price","expected_price")
def _check_selling_price(self):
for rec in self:
if rec.selling_price !=0 and rec.selling_price< rec.expected_price*0.9:
raise odoo.exceptions.ValidationError("售价不能低于报价的90%")
警告:
永远使用odoo.tools.float_utils包中的float_compare()
and float_is_zero()
方法来处理浮点数据。
确保当selling price 和 expected price发生变化的时候都会触发约束。
SQL约束通常比Python约束更高效,如果考虑性能,SQL约束总是优先Python约束。
我们的房地产模块开始看上去好多了,我们添加了一些商业逻辑,现在可以确保数据是有效的,但是用户界面稍微有点丑陋,让我们看看如何改进它?