odoo 开发入门教程系列-约束(Constraints)
Posted 授客的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了odoo 开发入门教程系列-约束(Constraints)相关的知识,希望对你有一定的参考价值。
约束(Constraints)
上一章介绍了向模型中添加一些业务逻辑的能力。我们现在可以将按钮链接到业务代码,但如何防止用户输入错误的数据?例如,在我们的房地产模块中,没有什么可以阻止用户设置负预期价格。
odoo提供了两种设置自动验证恒定式的方法:Python约束
and SQL约束
。
SQL
参考:与此主题相关的文档可以查看 Models 和PostgreSQL文档
我们通过模型属性_sql_constraints
来定义SQL约束,该属性被赋值为一个包含三元组(name, sql_definition, message)
的列表,其中name
为一个合法的SQL约束名称, sql_definition
为表约束表达式,message
为错误消息。
class AccountAnalyticDistribution(models.Model):
_name = \'account.analytic.distribution\'
_description = \'Analytic Account Distribution\'
_rec_name = \'account_id\'
account_id = fields.Many2one(\'account.analytic.account\', string=\'Analytic Account\', required=True)
percentage = fields.Float(string=\'Percentage\', required=True, default=100.0)
name = fields.Char(string=\'Name\', related=\'account_id.name\', readonly=False)
tag_id = fields.Many2one(\'account.analytic.tag\', string="Parent tag", required=True)
_sql_constraints = [
(\'check_percentage\', \'CHECK(percentage >= 0 AND percentage <= 100)\',
\'The percentage of an analytic distribution should be between 0 and 100.\')
]
一个简单的示例--唯一约束
class BlogTagCategory(models.Model):
_name = \'blog.tag.category\'
_description = \'Blog Tag Category\'
_order = \'name\'
name = fields.Char(\'Name\', required=True, translate=True)
tag_ids = fields.One2many(\'blog.tag\', \'category_id\', string=\'Tags\')
_sql_constraints = [
(\'name_uniq\', \'unique (name)\', "Tag category already exists !"),
]
练习--添加SQL约束
添加以下约束到对应模型:
- 房产预期价格必须为正数
- 房产售价必须为正数
- 报价必须为正数
- 房产标签名称和类型名称必须唯一
使用-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)
例如,如果某些报价的价格为零,则无法应用约束。可以删除、修正有问题的数据以应用新的约束。
修改odoo14\\custom\\estate\\models\\estate_property.py
,添加SQL约束
_sql_constraints = [
(\'check_expected_price\', \'CHECK(expected_price > 0)\', \'expected price should be positive.\'),
(\'check_selling_price\', \'CHECK(selling_price > 0)\', \'selling price should be positive.\')
]
注意:当selling_price为null
时,也通过CHECK(selling_price > 0)
校验的
修改odoo14\\custom\\estate\\models\\estate_property_tag.py
,添加SQL约束
_sql_constraints = [(\'check_tag\', \'unique(name)\', \'Tag name must be unique !\')]
修改odoo14\\custom\\estate\\models\\estate_property_type.py
,添加SQL约束
_sql_constraints = [(\'check_name\', \'unique(name)\', \'Type name must be unique !\')]
重启服务验证
预期效果动画:https://www.odoo.com/documentation/14.0/zh_CN/_images/sql_01.gif
https://www.odoo.com/documentation/14.0/zh_CN/_images/sql_02.gif
Python
参考: 主题关联文档可查看constrains()
.
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
@api.constrains(\'quantity\')
def check_quantity(self):
for quant in self:
if quant.location_id.usage != \'inventory\' and quant.lot_id and quant.product_id.tracking == \'serial\' \\
and float_compare(abs(quant.quantity), 1, precision_rounding=quant.product_uom_id.rounding) > 0:
raise ValidationError(_(\'The serial number has already been assigned: \\n Product: %s, Serial Number: %s\') % (quant.product_id.display_name, quant.lot_id.name))
练习--添加Python约束
添加售价不能低于预期价格90%的约束
提示: 报价生效前,保持售价为0。你需要对校验进行微调,以便把这个考虑在内。
警告
当和浮点数打交道时,总是使用从
odoo.tools.float_utils
导入的float_compare()
和float_is_zero()
方法
确保每次售价或者预期价格改变时,自动触发约束
修改odoo14\\custom\\estate\\models\\estate_property.py
导入 ValidationError
from odoo.exceptions import ValidationError
最末尾添加以下代码
@api.constrains(\'selling_price\', \'expected_price\')
def _check_selling_price(self):
for record in self:
if record.selling_price < self.expected_price * 0.9:
raise ValidationError("selling price can`t not lower then 90 percent of expected price")
重启服务,浏览器中验证
预期效果动画:https://www.odoo.com/documentation/14.0/zh_CN/_images/python.gif
SQL约束通常比Python约束更效率。当性能很重要时,总是首选SQL约束而不是Python约束。
作者:授客
微信/QQ:1033553122
全国软件测试QQ交流群:7156436
Git地址:https://gitee.com/ishouke
友情提示:限于时间仓促,文中可能存在错误,欢迎指正、评论!
作者五行缺钱,如果觉得文章对您有帮助,请扫描下边的二维码打赏作者,金额随意,您的支持将是我继续创作的源动力,打赏后如有任何疑问,请联系我!!!
微信打赏
支付宝打赏 全国软件测试交流QQ群
Odoo constraints 使用教程
在日常开发Odoo的过程中,我们不免要用到Constraints,中文就是约束。
首先我们来介绍下Odoo里面的两种Constraints。
SQL Constraints:就是添加一个数据库的约束。
_sql_constraints是odoo的属性,是一个元祖的列表,每个元祖是一个数据库约束。元祖的第一个元素是约束名字,第二个元素是约束规则(postgresql约束规则),第三个参数是如果违反约束弹出来的警告信息。
_sql_constraints = [ (‘name_description_check‘, ‘CHECK(name != description)‘, "The title of the course should not be the description"), (‘name_unique‘, ‘UNIQUE(name)‘, "The course title must be unique"), ]
注意在使用SQL Constraints,需要确保当前数据库里面没有违反该约束的数据,如果有违反约束的数据在更新模块的时候系统日志里面会有警告信息,大家要注意这个。
Constraints:
@api.constrains(‘instructor_id‘, ‘attendee_ids‘) def _check_instructor_not_in_attendees(self): for r in self: if r.instructor_id and r.instructor_id in r.attendee_ids: raise exceptions.ValidationError("A session‘s instructor can‘t be an attendee")
odoo的Constraints,是通过装饰器@api.constrains(字段),每次记录修改的时候,如果包含了装饰器定义的字段就会触发下面的方法,所以需要在方法里面判断是否违反约束,如果违反,则通过raise异常来弹出警告框并阻止记录保存。使用odoo Constraints的时候就算是系统内已经有违反约束的记录也可以对新记录生效。
以上是关于odoo 开发入门教程系列-约束(Constraints)的主要内容,如果未能解决你的问题,请参考以下文章
Error:(27, 13) Failed to resolve: com.android.support.constraint:constraint-layout:1.0.2约束布局constrai