Odoo 16:如何让Many2one字段返回指定字段而非默认ID
可行实现方法
方法1:重写关联模型name_get()+关联字段(推荐)
这是Odoo中最常用的方案,既能控制Many2one的显示文本,又能方便获取目标字段值。
控制显示文本
修改coa_ledgers模型的name_get()方法,让所有关联它的Many2one字段默认显示acc_name:
class COALedgers(models.Model): _name = 'coa_ledgers' _description = 'COA Ledgers' id = fields.Integer() acc_name = fields.Char(string='Account Name') ledger_acc = fields.Char(string='Ledger Account') def name_get(self): return [(rec.id, rec.acc_name or '') for rec in self]
获取关联的ledger_acc值
如果需要在banks中直接使用该值,有两种方式:
- 代码中直接访问:业务逻辑里用
bank_record.ledger_acc.ledger_acc即可拿到对应值。 - 新增关联字段:在
banks模型里加一个related字段,方便视图显示、导出或批量操作:
class Banks(models.Model): _name = 'banks' _description = 'Banks' id = fields.Integer() bank_name = fields.Char(string='Bank Name') ledger_acc = fields.Many2one('coa_ledgers', string='Ledger A/c') ledger_acc_code = fields.Char( string='Ledger Account Code', related='ledger_acc.ledger_acc', store=True # 可选,需要存储则开启 )
方法2:为Many2one指定自定义selection(小数据量场景)
如果coa_ledgers数据量小且更新不频繁,可以直接在banks的Many2one字段里定义动态选项,手动指定显示文本为acc_name:
class Banks(models.Model): _name = 'banks' _description = 'Banks' id = fields.Integer() bank_name = fields.Char(string='Bank Name') def _get_ledger_options(self): return [(rec.id, rec.acc_name) for rec in self.env['coa_ledgers'].search([])] ledger_acc = fields.Many2one( 'coa_ledgers', string='Ledger A/c', selection=_get_ledger_options ) # 同样用related字段获取ledger_acc值 ledger_acc_code = fields.Char(string='Ledger Account Code', related='ledger_acc.ledger_acc', store=True)
注意:这种方式需要刷新视图才能同步coa_ledgers的新增/修改记录,不适合数据变动频繁的场景。
方法3:视图层上下文控制显示(不影响其他关联字段)
如果不想修改coa_ledgers的全局name_get()(避免影响其他模块的关联字段),可以通过视图上下文控制该特定Many2one的显示:
第一步:让coa_ledgers支持上下文切换显示
class COALedgers(models.Model): _name = 'coa_ledgers' _description = 'COA Ledgers' id = fields.Integer() acc_name = fields.Char(string='Account Name') ledger_acc = fields.Char(string='Ledger Account') def name_get(self): result = [] # 检查上下文是否要求显示acc_name if self.env.context.get('show_acc_name'): for rec in self: result.append((rec.id, rec.acc_name or '')) else: # 保留原有name_get逻辑(比如显示ledger_acc或默认name) result = super().name_get() return result
第二步:在banks视图中添加上下文
在表单/树视图的ledger_acc字段定义里加入上下文参数:
<field name="ledger_acc" string="Ledger A/c" context="{'show_acc_name': True}"/>
这样只有这个视图的Many2one会显示acc_name,其他关联coa_ledgers的字段不受影响。获取ledger_acc值的方式和方法1一致。
方法4:计算字段模拟Many2one(特殊场景)
如果确实需要让字段“返回”ledger_acc字符串而非关联id,可用计算字段模拟选择功能,但会失去Many2one的关联特性(比如自动同步、关联校验),仅适合特殊需求:
class Banks(models.Model): _name = 'banks' _description = 'Banks' id = fields.Integer() bank_name = fields.Char(string='Bank Name') # 隐藏的实际关联字段 ledger_acc_id = fields.Many2one('coa_ledgers', invisible=True) # 对外显示的计算字段 ledger_acc = fields.Char( string='Ledger A/c', compute='_compute_ledger_acc', inverse='_inverse_ledger_acc' ) def _compute_ledger_acc(self): for rec in self: rec.ledger_acc = rec.ledger_acc_id.ledger_acc if rec.ledger_acc_id else '' def _inverse_ledger_acc(self): for rec in self: if rec.ledger_acc: # 根据ledger_acc查找对应记录 ledger = self.env['coa_ledgers'].search([('ledger_acc', '=', rec.ledger_acc)], limit=1) rec.ledger_acc_id = ledger.id if ledger else False
需要在视图中给ledger_acc配置下拉选择widget(比如自定义或用selection),复杂度较高,不推荐常规使用。
内容的提问来源于stack exchange,提问作者Ahmed Haroon
相关产品推荐
相关产品推荐

