Odoo模型字段计算异常:onchange实现除法运算失败
问题分析与解决方案
嘿,我看了你这段Odoo代码,问题出在几个关键地方,让我给你捋一捋:
核心问题点
- 方法位置错误:你把
@api.onchange方法嵌套在了ProductTemplate类的计算方法循环内部,这完全不符合Odoo的模型定义规则!这个onchange方法本应属于sr.sale.price.history模型,Odoo根本识别不到你现在写的这个方法。 - onchange的触发场景限制:就算你把onchange方法放对位置,它也只在用户在表单界面手动修改字段时触发。而你是通过代码批量调用
create创建历史记录的,这种场景下onchange不会自动执行,所以amount_after_disc还是不会被赋值。
推荐解决方案:使用计算字段
因为amount_after_disc是依赖total_price和product_uom_qty的派生值,用计算字段是最适合的方案——不管是创建记录还是后续修改依赖字段,都会自动更新计算结果,还能避免手动赋值的遗漏。
修改后的sr.sale.price.history模型代码
class srSalePriceHistory(models.Model): _name = 'sr.sale.price.history' _description = 'Sale Price History' name = fields.Many2one("sale.order.line",string="Sale Order Line") partner_id = fields.Many2one("res.partner",string="Customer") user_id = fields.Many2one("res.users",string="Sales Person") product_tmpl_id = fields.Many2one("product.template",string="Template Id") variant_id = fields.Many2one("product.product",string="Product") sale_order_id = fields.Many2one("sale.order",string="Sale Order") sale_order_date = fields.Datetime(string="Order Date") product_uom_qty = fields.Float(string="Quantity") unit_price = fields.Float(string="Price") currency_id = fields.Many2one("res.currency",string="Currency Id") total_price = fields.Monetary(string="Total") # 改成计算字段,store=True可选(需要存储时添加) amount_after_disc = fields.Float( string="After Disc", compute='_compute_amount_after_disc', store=True, help="Calculated as total_price / product_uom_qty" ) @api.depends('total_price', 'product_uom_qty') def _compute_amount_after_disc(self): for rec in self: # 必须处理除数为0的情况,避免系统报错 if rec.product_uom_qty != 0 and rec.total_price is not None: rec.amount_after_disc = rec.total_price / rec.product_uom_qty else: rec.amount_after_disc = 0.0 # 可选:添加onchange方法,在表单编辑时实时预览计算结果 @api.onchange('total_price', 'product_uom_qty') def onchange_amount_after_disc(self): if self.product_uom_qty != 0 and self.total_price is not None: self.amount_after_disc = self.total_price / self.product_uom_qty else: self.amount_after_disc = 0.0
额外清理工作
记得把之前嵌套在ProductTemplate类的_get_sale_price_history方法里的那个错误的onchange_field方法删掉,那个位置完全不符合Odoo的开发规范。
关键说明
store=True:如果需要在数据库中存储计算值(比如用于筛选、排序或者报表),就保留这个参数;如果不需要存储,每次使用时实时计算,可以去掉。- 除数为0的处理:一定要加上这个判断,否则当
product_uom_qty为0时会抛出除以0的异常,导致系统崩溃。
内容的提问来源于stack exchange,提问作者Muhammad S. Eltyar




