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

Odoo 12中many2many字段track_visibility不支持及失效问题求助

在Odoo 12中实现Many2many字段的变更追踪

确实,Odoo 12里mail.thread的track_visibility原生就不支持many2many字段——毕竟这类字段是关联集合,系统默认的追踪逻辑只处理单个值的变更,没法自动识别集合里的增删操作。不过我们可以通过重写核心追踪方法来解决这个问题,下面给你两种可行的方案:

方案一:重写_message_track方法(推荐,覆盖所有场景)

这是最全面的解决方案,不管是前端表单修改、后台批量操作还是代码层面的字段变更,都能触发追踪消息。核心思路是扩展mail.thread的_message_track方法,让它能识别并处理many2many字段的变更。

代码示例

from odoo import models, fields, api

class YourTargetModel(models.Model):
    _name = 'your.target.model'  # 替换成你的模型名称
    _inherit = ['mail.thread']  # 确保模型继承mail.thread

    # 定义你的many2many字段,保留track_visibility标记
    related_partners = fields.Many2many(
        'res.partner',
        string="关联合作伙伴",
        track_visibility='onchange'
    )

    def _message_track(self, tracked_fields, initial_values):
        # 先调用父类方法处理普通字段的追踪
        res = super(YourTargetModel, self)._message_track(tracked_fields, initial_values)
        
        for record in self:
            # 遍历所有被标记为追踪的字段
            for field_name in tracked_fields:
                field_info = tracked_fields[field_name]
                field = record._fields[field_name]
                
                # 只处理many2many类型且track_visibility为onchange/always的字段
                if field.type == 'many2many' and field_info.get('track_visibility') in ['onchange', 'always']:
                    # 获取初始值和当前值
                    initial_records = initial_values.get(record.id, {}).get(field_name, record.browse())
                    current_records = record[field_name]
                    
                    # 计算新增和移除的记录
                    added_records = current_records - initial_records
                    removed_records = initial_records - current_records
                    
                    if added_records or removed_records:
                        msg_segments = []
                        if added_records:
                            added_names = ', '.join([rec.display_name for rec in added_records])
                            msg_segments.append(f"添加了: {added_names}")
                        if removed_records:
                            removed_names = ', '.join([rec.display_name for rec in removed_records])
                            msg_segments.append(f"移除了: {removed_names}")
                        
                        # 组装消息内容并发送
                        track_message = '; '.join(msg_segments)
                        record.message_post(
                            body=f"<p><b>{field.string}</b> 已变更: {track_message}</p>",
                            message_type='notification',
                            subtype_id=self.env.ref('mail.mt_note').id
                        )
        return res

关键说明

  • 这段代码会自动对比many2many字段的初始值和当前值,识别出新增/移除的记录
  • 生成的消息会直接出现在模型的聊天流中,和原生字段的追踪消息格式保持一致
  • 支持所有触发字段变更的场景,包括前端编辑、后台批量修改、API调用等

方案二:通过onchange方法手动触发(仅前端场景)

如果你只需要处理前端表单的修改,可以直接给many2many字段添加onchange方法,手动生成追踪消息。不过这种方式无法覆盖后台操作和代码变更的场景。

代码示例

from odoo import models, fields, api

class YourTargetModel(models.Model):
    _name = 'your.target.model'
    _inherit = ['mail.thread']

    related_partners = fields.Many2many(
        'res.partner',
        string="关联合作伙伴",
        track_visibility='onchange'
    )

    @api.onchange('related_partners')
    def _onchange_related_partners(self):
        # 仅对已有记录生效(新建记录没有origin)
        if self._origin.id:
            initial_records = self._origin.related_partners
            current_records = self.related_partners
            
            added_records = current_records - initial_records
            removed_records = initial_records - current_records
            
            if added_records or removed_records:
                msg_segments = []
                if added_records:
                    added_names = ', '.join([rec.display_name for rec in added_records])
                    msg_segments.append(f"添加了: {added_names}")
                if removed_records:
                    removed_names = ', '.join([rec.display_name for rec in removed_records])
                    msg_segments.append(f"移除了: {removed_names}")
                
                track_message = '; '.join(msg_segments)
                self.message_post(
                    body=f"<p><b>{self._fields['related_partners'].string}</b> 已变更: {track_message}</p>",
                    message_type='notification',
                    subtype_id=self.env.ref('mail.mt_note').id
                )

注意事项

  • 确保你的模型已经正确继承mail.thread,否则消息无法发送到聊天流
  • 如果many2many关联的模型没有display_name字段(或者你想显示其他字段),可以替换成对应的字段名称(比如name)
  • 测试时要覆盖所有变更场景:新增记录、移除记录、全选/清空集合等,确保消息生成正确

内容的提问来源于stack exchange,提问作者nguyen thanh Dinh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:36:36