Odoo中出现无法适配'NewId'类型错误,求解决方案
Odoo:编辑/删除行触发「无法适配'NewId'类型」错误及计算字段值随依赖项变动问题
原问题描述
编辑或删除销售订单行时,触发「无法适配'NewId'类型」错误,原实现代码如下:
@api.multi @api.depends('product_id','order_id') def _get_cost_price_currency_update2(self): for record in self: param2 =() query2 = '''SELECT hpp_update,cost_price_set_lock FROM sale_order_line WHERE order_id = %s AND product_id = %s ''' param2 +=(record.order_id.id,record.product_id.id) self.env.cr.execute(query2,param2) query_result_lines2= self.env.cr.dictfetchall() for line in query_result_lines2: if line['hpp_update']: cost_price_set_update = line['hpp_update'] else: cost_price_set_update = line['cost_price_set_lock'] record.cost_price_set_update = cost_price_set_update cost_price_set_update = fields.Float(string='CPP Update', compute=_get_cost_price_currency_update2)
更新后问题
修改代码改用ORM查询后,新问题出现:cost_price_set_update的值始终随cost_price_set_lock的计算结果变动,无法保留首次存储的值。修改后的代码:
cost_price_set_lock = fields.Float(string='CPP Lock',compute=_get_cost_price_currency, store=True) @api.depends('order_id') def _get_cost_price_currency_update2(self): cost_price_set_update2 = '' invoice_pool = self.env['sale.order.line'] for record2 in self: for invoice in invoice_pool.search([('order_id', '=', record2.order_id.id), ('product_id', '=', record2.product_id.id)]): if invoice.hpp_update: cost_price_set_update2 = invoice.hpp_update else: cost_price_set_update2 = invoice.cost_price_set_lock record2.cost_price_set_update = cost_price_set_update2 cost_price_set_update = fields.Float(string='CPP Update', compute=_get_cost_price_currency_update2)
问题根源与修复方案
1. 「无法适配'NewId'类型」错误原因
原代码直接使用原生SQL查询时,未处理Odoo中新建未保存记录的临时ID(NewId)。新建记录会被分配形如__export__.xxxx的临时ID,直接传入SQL查询无法映射到数据库真实ID,从而触发类型错误。
2. 原错误修复代码
改用Odoo ORM查询替代原生SQL,ORM会自动处理临时ID的映射逻辑:
@api.depends('product_id', 'order_id') def _get_cost_price_currency_update2(self): for record in self: # ORM查询自动处理NewId映射 lines = self.env['sale.order.line'].search([ ('order_id', '=', record.order_id.id), ('product_id', '=', record.product_id.id) ]) # 明确取第一条匹配记录的值(需根据业务调整多条记录的处理逻辑) if lines: line = lines[0] record.cost_price_set_update = line.hpp_update or line.cost_price_set_lock else: record.cost_price_set_update = 0.0 cost_price_set_update = fields.Float(string='CPP Update', compute=_get_cost_price_currency_update2)
3. 「值随cost_price_set_lock变动」问题修复
当前cost_price_set_update是非存储型计算字段,每次依赖项变动都会重新计算。若要保留首次计算的值,需将字段改为存储型计算字段,并控制仅在特定条件下更新:
cost_price_set_update = fields.Float( string='CPP Update', compute=_get_cost_price_currency_update2, store=True, # 开启字段存储 readonly=True # 禁止手动修改 ) @api.depends('product_id', 'order_id', 'cost_price_set_lock') def _get_cost_price_currency_update2(self): for record in self: # 仅当字段未设置时更新,保留首次计算的值 if not record.cost_price_set_update: lines = self.env['sale.order.line'].search([ ('order_id', '=', record.order_id.id), ('product_id', '=', record.product_id.id) ]) if lines: line = lines[0] record.cost_price_set_update = line.hpp_update or line.cost_price_set_lock else: record.cost_price_set_update = 0.0
额外注意事项
- 若
hpp_update或cost_price_set_lock可能为空,需设置默认值(如0.0)避免类型错误 - 当查询多条
sale.order.line时,需明确取值逻辑(如取第一条、最新创建的记录),避免循环覆盖值
内容的提问来源于stack exchange,提问作者Nur Faiz
相关产品推荐
相关产品推荐

