Odoo@onchange监听任务阶段变更创建活动时报NewId对象不可迭代错误求助
问题原因
TypeError: 'NewId' object is not iterable报错的核心是@api.onchange的运行机制不匹配当前需求:
- Odoo触发
@api.onchange时,会生成仅存在于内存的临时记录对象,用特殊的NewId类型替代真实的数据库主键ID,此时代码中调用的self._origin.id本质是NewId对象而非整数,传入mail.activity要求为整数类型的res_id字段就会触发类型错误。 - 从设计层面看,
@api.onchange仅用于前端编辑时的字段预赋值,不应该执行创建活动这类写入数据库的持久化操作,onchange触发时记录可能还未保存到数据库,关联逻辑必然存在隐患。
修正方案
将监听阶段变更的逻辑从重写@api.onchange改为重写write方法,该方法会在记录实际提交到数据库后触发,所有记录ID都是真实有效的整数值:
from datetime import datetime, timedelta from odoo import api, fields, models class ProjectSetAndDateType(models.Model): _inherit = 'project.task.type' last_stage = fields.Boolean(string="Fertigstellungsstufe") class ProjectSetEndDate(models.Model): _inherit = 'project.task' def write(self, vals): res = super().write(vals) # 仅当stage_id被修改时触发逻辑 if 'stage_id' in vals: for task in self: if task.stage_id.last_stage: # 赋值完成状态和结束时间 task.write({ 'kanban_state': "done", 'date_finished': datetime.now() }) # 创建归档提醒活动 activity_deadline = datetime.now() + timedelta(days=30) data = { 'res_id': task.id, 'res_model': 'project.task', 'res_model_id': self.env['ir.model']._get_id('project.task'), 'user_id': task.project_id.user_id.id, 'summary': 'Aufgabe archivieren nach Fertigstellung', 'activity_type_id': self.env.ref('project_set_end_date.mail_set_end_date_archive').id, 'date_deadline': activity_deadline } self.env['mail.activity'].create(data) return res
优化说明
- 用
_get_id方法替代search取模型ID,性能更优,写法更简洁 - 新增批量处理逻辑,兼容同时修改多个任务的场景,避免单条记录报错导致整个操作失败
- 直接传入
datetime对象即可,不需要手动转字符串,Odoo ORM会自动处理时区和格式转换 - 移除了
_origin的调用,此时记录已经保存到数据库,直接取当前对象的属性即可
内容的提问来源于stack exchange,提问作者cataclysmic
相关产品推荐
相关产品推荐

