Odoo 16模型关联异常:self.id返回_unknown(实际ID,)错误
Odoo 16 模型关联时
_unknown(实际ID,)问题排查与解决 问题背景
基于Odoo 16开发付款审批流程,涉及两个核心模型:
- nkap_custom_paiement:继承
account.payment,新增related_payment_id字段关联account.payment.register,用于记录关联的付款注册向导,包含多级审批方法。 - CustomPaymentRegister:继承
account.payment.register(临时向导模型),负责创建account.payment记录并反向关联到自身。
需求是让通过向导创建的付款完成审批后,回调向导的action_create_payments方法,但关联过程中self.id始终显示为_unknown(实际ID,)格式,导致关联关系失效。
核心异常代码片段:
# CustomPaymentRegister类的action_submit_for_approval方法 def action_submit_for_approval(self): payment_vals = self._collect_payment_vals() payment = self.env['account.payment'].create(payment_vals) self.payment_id = payment.id payment.related_payment_id = self.id # 此处self.id显示为_unknown(xxx,) payment.action_submit_for_approval()
问题原因
account.payment.register是临时(transient)模型,这类模型的记录会在会话结束或特定操作后被自动清理。当直接使用self.id关联时,Odoo可能因为临时模型记录的状态(未持久化或标记为待清理),导致ID显示为_unknown格式,本质是模型记录的引用有效性问题。此外,临时模型记录创建后若未正确保存,或关联时会话上下文发生变化,也会触发该异常。
解决方案
方案1:使用记录集直接赋值替代ID赋值
Odoo ORM优先推荐用记录集操作,避免直接使用ID,可自动处理模型上下文和记录有效性:
def action_submit_for_approval(self): payment_vals = self._collect_payment_vals() payment = self.env['account.payment'].create(payment_vals) self.payment_id = payment payment.related_payment_id = self # 直接赋值记录集而非ID payment.action_submit_for_approval()
方案2:调整临时模型记录保留时长(应急方案)
临时模型默认自动清理,若需强制保留记录,可修改transient_max_hours参数,但此方案违背临时模型设计初衷,可能造成数据冗余:
class CustomPaymentRegister(models.TransientModel): _inherit = 'account.payment.register' _transient_max_hours = 24 # 设置记录保留时长,单位小时 payment_id = fields.Many2one('account.payment', string='Created Payment') # 其他原有代码...
方案3:重构逻辑,避免临时模型与永久模型双向关联
临时模型设计初衷是一次性操作,不适合长期关联。建议调整流程:
- 在
account.payment中存储向导关键参数(而非关联向导记录) - 审批完成后,根据参数重新初始化向导并执行目标方法
# nkap_custom_paiement新增字段存储向导参数 class nkap_custom_paiement(models.Model): _inherit = ['account.payment'] # 新增字段存储向导必要参数 register_journal_id = fields.Many2one('account.journal') register_payment_date = fields.Date() # 其他原有字段... # CustomPaymentRegister的action_submit_for_approval方法 def action_submit_for_approval(self): payment_vals = self._collect_payment_vals() # 附加向导参数到付款记录 payment_vals.update({ 'register_journal_id': self.journal_id.id, 'register_payment_date': self.payment_date, # 其他需要的参数 }) payment = self.env['account.payment'].create(payment_vals) payment.action_submit_for_approval() # 审批完成后重构向导调用 def action_cashier_approval(self): company_id=self.env.company if self.env.user.id in company_id.po_fourth_approver_ids.ids: self.write({'state': 'posted'}) # 重新初始化向导并执行方法 register = self.env['account.payment.register'].create({ 'journal_id': self.register_journal_id.id, 'payment_date': self.register_payment_date, # 其他必要参数 }) register.action_create_payments() else: raise ValidationError(_("Seul %s peut approver !"% company_id.po_fourth_approver_ids.id ))
关键注意事项
- 临时模型(transient)不适合长期数据关联,设计流程时应尽量避免双向绑定
- Odoo中操作记录优先使用记录集而非直接ID,ORM会自动处理记录的有效性和上下文
- 若必须关联临时模型,确保在会话有效期内完成操作,避免记录被自动清理
内容的提问来源于stack exchange,提问作者Yaya
相关产品推荐
相关产品推荐

