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

Odoo双向关联限制处理:添加模型关联触发KeyError报错

问题:Odoo添加One2many字段后触发KeyError: 'gpscontrol.wialon_unit'

尝试在gpscontrol.wialon_unit模型中添加两个One2many字段,关联motion.internal_device和motion.internal_card,实现为unit绑定设备和SIM卡的功能,但字段添加后Odoo抛出服务器错误。

模型代码

class wialon_unit(models.Model):
    _name = "gpscontrol.wialon_unit"
    _inherit = ["motion.tracking_unit"]
    _rec_name = "name"
    _sql_constraints = [
        ('name_uniq', 'unique (id_wialon)',
         'El id wialon no puede repetirse')
    ]

    device_rel = fields.One2many(
        'motion.internal_device', string="Dispositivo")
    card_rel = fields.One2many(
        'motion.internal_card', string="SIM")

报错信息

RPC_ERROR
Odoo Server Error
Traceback (most recent call last):
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/api.py", line 886, in get
    return field_cache[record._ids[0]]
KeyError: 196

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/fields.py", line 1082, in __get__
    value = env.cache.get(record, self)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/api.py", line 889, in get
    raise CacheMiss(record, field)
odoo.exceptions.CacheMiss: 'ir.actions.act_window(196,).search_view'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/addons/base/models/ir_http.py", line 237, in _dispatch
    result = request.dispatch()
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/http.py", line 698, in dispatch
    result = self._call_function(**self.params)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/http.py", line 368, in _call_function
    return checked_call(self.db, *args, **kwargs)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/service/model.py", line 94, in wrapper
    return f(dbname, *args, **kwargs)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/http.py", line 357, in checked_call
    result = self.endpoint(*a, **kw)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/http.py", line 921, in __call__
    return self.method(*args, **kw)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/http.py", line 546, in response_wrap
    response = f(*args, **kw)
  File "/Users/admin/Desktop/back_end/odoo/odoo/addons/web/controllers/main.py", line 1603, in load
    action = request.env[action_type].sudo().browse([action_id]).read()
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/addons/base/models/ir_actions.py", line 255, in read
    result = super(IrActionsActWindow, self).read(fields, load=load)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/models.py", line 3235, in read
    return self._read_format(fnames=fields, load=load)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/models.py", line 3255, in _read_format
    vals[name] = convert(record[name], record, use_name_get)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/models.py", line 5916, in __getitem__
    return self._fields[key].__get__(self, type(self))
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/fields.py", line 1131, in __get__
    self.compute_value(recs)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/fields.py", line 1290, in compute_value
    records._compute_field_value(self)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/models.py", line 4269, in _compute_field_value
    fields.determine(field.compute, self)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/fields.py", line 87, in determine
    return needle(*args)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/addons/base/models/ir_actions.py", line 222, in _compute_search_view
    fvg = self.env[act.res_model].fields_view_get(act.search_view_id.id, 'search')
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/api.py", line 540, in __getitem__
    return self.registry[model_name]._browse(self, (), ())
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/modules/registry.py", line 182, in __getitem__
    return self.models[model_name]
Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/http.py", line 654, in _handle_exception
    return super(JsonRequest, self)._handle_exception(exception)
  File "/Users/admin/Desktop/back_end/odoo/odoo/odoo/http.py", line 301, in _handle_exception
    raise exception.with_traceback(None) from new_cause
KeyError: 'gpscontrol.wialon_unit'

已做检查

确认模块manifest.py的依赖配置包含相关模块:

"depends": [
        "base",
        "base_geoengine",
        "base_geolocalize",
        "motion_service_orders"
    ],

解决方案

1. 补全One2many字段的必填参数

One2many字段必须指定inverse_name参数,对应关联模型中指向当前模型的Many2one字段名。假设motion.internal_device和motion.internal_card中都有一个名为unit_id的Many2one字段指向gpscontrol.wialon_unit(或其继承的motion.tracking_unit),修改字段定义如下:

device_rel = fields.One2many(
    'motion.internal_device', inverse_name='unit_id', string="Dispositivo")
card_rel = fields.One2many(
    'motion.internal_card', inverse_name='unit_id', string="SIM")

若关联模型中的字段名不是unit_id,替换为实际字段名即可。

2. 确保模型与依赖加载正常

  • 确认gpscontrol.wialon_unit所在模块已正确安装,且motion_service_orders模块确实包含motion.tracking_unit、motion.internal_device和motion.internal_card三个模型。
  • 重启Odoo服务,然后升级当前模块,确保新字段被正确同步到数据库。

3. 清理动作窗口缓存

错误中提到的CacheMiss可能是旧动作窗口缓存导致:

  • 清除浏览器缓存后重新登录Odoo。
  • 开启开发者模式,进入设置 > 技术 > 动作 > 窗口动作,找到ID为196的动作,检查其模型字段是否正确指向gpscontrol.wialon_unit,若存在错误可修改或删除该动作后重新生成。

4. 验证模型继承正确性

确认motion.tracking_unit模型被正确继承,继承链中没有命名冲突或定义错误,保证gpscontrol.wialon_unit能被Odoo识别为有效模型。

内容的提问来源于stack exchange,提问作者David Heredia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:57:34