Odoo 16通过One2many关联跨模型写入字段无效果问题排查
Odoo 16云托管版:关联System时同步Press字段数据失败问题解决
我使用云托管版Odoo 16.0,想要在Press表单关联System时,把Press的字段数据同步到关联的System模型中。我用@api.onchange()监听system_ids字段变化,遍历关联的System记录并调用write()方法写入press_oem_serial字段,执行时没有报错,但数据没成功写入,调试确认已经走到write()语句。
相关代码如下:
from odoo import models, fields, api class Press(models.Model): _name = 'press.press' _description = 'Press Model' name = fields.Char() system_ids = fields.One2many('system.system', 'press_id', string='Systems') oem_serial = fields.Char("Press OEM Serial Num.") @api.onchange('system_ids') def _onchange_system_ids(self): if self.system_ids: for record in self.system_ids: if record.press_oem_serial == False: record.write({'press_oem_serial': self.oem_serial}) class System(models.Model): _name = 'system.system' _description = 'System Model' name = fields.Char() press_id = fields.Many2one(comodel_name='press.press', string="Press") press_oem_serial = fields.Char("Press OEM Serial Num.")
问题原因
@api.onchange方法里的修改仅作用于表单临时数据,不会直接写入数据库——除非用户保存当前Press记录。而且如果是刚在One2many字段新增的System记录,还处于未提交到数据库的草稿状态,直接调用write()也无法正确持久化这些修改。
解决方案
方案一:用计算字段自动同步(推荐)
把System模型的press_oem_serial改成计算字段,直接从关联的Press取值,无需手动同步,数据会自动关联:
class System(models.Model): _name = 'system.system' _description = 'System Model' name = fields.Char() press_id = fields.Many2one(comodel_name='press.press', string="Press") press_oem_serial = fields.Char("Press OEM Serial Num.", compute='_compute_press_oem_serial', store=True) @api.depends('press_id', 'press_id.oem_serial') def _compute_press_oem_serial(self): for record in self: record.press_oem_serial = record.press_id.oem_serial if record.press_id else False
store=True会把计算结果保存到数据库,既保证数据实时同步,也不影响性能。
方案二:在Press保存时手动同步
如果必须用手动同步的方式,在Press的create和write方法里处理数据同步,同时保留onchange更新表单临时值:
class Press(models.Model): _name = 'press.press' _description = 'Press Model' name = fields.Char() system_ids = fields.One2many('system.system', 'press_id', string='Systems') oem_serial = fields.Char("Press OEM Serial Num.") def write(self, vals): res = super(Press, self).write(vals) # 当修改oem_serial或关联的system_ids时同步数据 if 'oem_serial' in vals or 'system_ids' in vals: for press in self: press.system_ids.filtered(lambda s: not s.press_oem_serial).write({'press_oem_serial': press.oem_serial}) return res @api.model_create_multi def create(self, vals_list): presses = super(Press, self).create(vals_list) for press in presses: press.system_ids.filtered(lambda s: not s.press_oem_serial).write({'press_oem_serial': press.oem_serial}) return presses @api.onchange('system_ids', 'oem_serial') def _onchange_system_ids(self): if self.system_ids and self.oem_serial: for record in self.system_ids: if not record.press_oem_serial: record.press_oem_serial = self.oem_serial
这样用户在表单上能看到临时同步效果,保存Press记录时,数据会真正写入数据库。
内容的提问来源于stack exchange,提问作者Harebrained
相关产品推荐
相关产品推荐

