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

Odoo 11跟踪字段历史记录获取及存储位置咨询

嘿,关于Odoo 11里提取跟踪字段历史记录的问题,我刚好有实操经验,给你拆解清楚:

一、先搞懂数据存在哪里

Odoo的字段跟踪记录(就是chatter里显示的那些字段变更日志),核心存在两张数据库表里:

  • mail_message:存储所有消息记录,包括字段变更、普通评论、系统通知等。其中和字段跟踪相关的记录,message_type值为'notification',subtype_id对应默认的字段变更子类型(mail.mt_field_change)。
  • mail_tracking_value:专门存字段变更的具体内容,每条记录通过message_id关联到mail_message,同时记录了字段技术名field_name、旧值old_value、新值new_value,以及对应的业务单据模型res_model和IDres_id。
二、提取数据的两种实用方式

1. 用Odoo ORM查询(推荐,符合框架规范)

因为你的业务模型继承了mail.thread,所以可以直接通过模型的message_ids关联到消息,再拿到跟踪值:

# 示例:获取某个销售订单的所有字段跟踪记录
# 替换成你实际用的模型,比如purchase.order、account.invoice等
order_model = self.env['sale.order']
# 替换成目标单据ID
target_order_id = 456
order = order_model.browse(target_order_id)

# 获取所有关联的跟踪值记录
tracking_records = order.message_ids.mapped('tracking_value_ids')

# 遍历解析记录(处理关联字段的显示值)
for track in tracking_records:
    old_val = track.old_value
    new_val = track.new_value
    field_info = order_model.fields_get([track.field_name])[track.field_name]
    
    # 如果是关联字段(比如many2one),转成用户能看懂的名称
    if field_info['type'] == 'many2one':
        if old_val:
            old_val = self.env[field_info['relation']].browse(int(old_val)).display_name
        if new_val:
            new_val = self.env[field_info['relation']].browse(int(new_val)).display_name
    
    print(f"[{track.create_date}] {field_info['string']}: {old_val} → {new_val}")

2. 直接SQL查询(适合批量导出数据)

如果需要快速批量导出数据做统计,直接写SQL效率更高:

SELECT
    mm.create_date AS change_time,
    res_model AS document_model,
    res_id AS document_id,
    mtv.field_name,
    -- 示例:处理销售订单partner_id字段的显示值
    CASE
        WHEN mtv.field_name = 'partner_id' THEN rp.name
        ELSE mtv.old_value
    END AS old_value,
    CASE
        WHEN mtv.field_name = 'partner_id' THEN rp_new.name
        ELSE mtv.new_value
    END AS new_value
FROM mail_tracking_value mtv
JOIN mail_message mm ON mtv.message_id = mm.id
-- 关联对应模型表获取显示值(按需添加)
LEFT JOIN res_partner rp ON mtv.old_value = rp.id AND mtv.field_name = 'partner_id'
LEFT JOIN res_partner rp_new ON mtv.new_value = rp_new.id AND mtv.field_name = 'partner_id'
-- 过滤你需要的模型和时间范围
WHERE mm.res_model = 'sale.order'
AND mm.create_date >= '2024-01-01'
ORDER BY mm.create_date DESC;
三、用于统计分析和绘图的思路

拿到数据后,你可以这么玩:

  • 把ORM查询结果转成pandas.DataFrame,方便做统计:
    import pandas as pd
    
    data = []
    for track in tracking_records:
        field_info = order_model.fields_get([track.field_name])[track.field_name]
        data.append({
            '时间': track.create_date,
            '单据ID': order.id,
            '字段名称': field_info['string'],
            '旧值': track.old_value,
            '新值': track.new_value
        })
    df = pd.DataFrame(data)
    
  • 基于DataFrame做统计:比如统计某个字段的变更次数、不同值之间的转换频率,或者绘制时间线图表展示单据状态的变化历程。
  • 如果要在Odoo内部展示图表,可以用web_graph模块或者自定义报表,把提取的跟踪数据作为数据源生成可视化图表。

内容的提问来源于stack exchange,提问作者meyou shizuka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:20:53