You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:33:15