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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 12:19:58