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

Odoo10:如何继承含Many2Many字段的Model至TransientModel?

实现方案:通过抽象模型共享字段与验证规则

在Odoo中,直接让临时模型(TransientModel)继承持久模型(Model)会引发架构冲突,因为二者基类不同。最优方案是用抽象模型(AbstractModel)作为中间层,让持久模型和向导模型共同继承它,从而实现字段、验证规则和业务逻辑的复用,避免重复代码和维护难题。

具体步骤

1. 提取抽象模型

把原模型的字段、验证约束、业务方法等核心逻辑迁移到抽象模型中:

from odoo import models, fields, api

class SapPlOutstandingCommentAbstract(models.AbstractModel):
    _name = "sap.pl.outstanding.comment.abstract"
    _description = "PL Manual Outstanding Comment Abstract"
    _rec_name = "plant_id"

    # 原模型所有字段
    plant_id = fields.Many2one('sap.mm.plant', string='Department', ondelete='restrict')
    period_id = fields.Many2one('account.period', string='Month', ondelete='restrict')
    description = fields.Many2one('sap.pl.id.mapping', string='Description', ondelete='restrict')
    category = fields.Many2one('sap.pl.comment.category', string='Category', ondelete='restrict')
    currency_id = fields.Many2one('res.currency', string='Currency', default=lambda self: self.env.user.company_id.currency_id)
    amount = fields.Monetary(string='Amount')
    action = fields.Selection([('take out/add in', 'Take Out/Add In'), ('move', 'Move')], string="Type of Comments")
    reconcile = fields.Boolean(string="Reconcile", default=False)
    move_to = fields.Many2one('sap.pl.id.mapping', string='Move To', ondelete='restrict')
    reason = fields.Text(string="Reason")
    status = fields.Selection([('open', 'Open'), ('closed', 'Closed')], string="Status", default="open")
    close_comment = fields.Boolean(default=False)
    can_select_action = fields.Boolean(default=False)
    can_close_comment = fields.Boolean(default=False)

    # 共享验证规则示例
    @api.constrains('amount')
    def _check_amount(self):
        for record in self:
            if record.amount <= 0:
                raise models.ValidationError("金额必须大于0")
    
    # 其他共享业务方法...

2. 修改原持久模型

让原模型继承抽象模型,保留自身特有的配置和字段:

class SapPlOutstandingComment(models.Model):
    _name = "sap.pl.outstanding.comment"
    _description = "PL Manual Outstanding Comment"
    _inherit = "sap.pl.outstanding.comment.abstract"

    # 持久模型特有的多对多字段(关联自身)
    reconcile_comment = fields.Many2many(
        'sap.pl.outstanding.comment',
        'sn_sap_pnl_oc_reconcile_rel',
        'sap_pl_outstanding_comment_id',
        'reconcile_comment_id',
        string='Outstanding Comment'
    )

3. 创建向导临时模型

向导模型继承抽象模型和TransientModel,并根据需求调整字段(如多对多关联表):

class SapPlOutstandingCommentWizard(models.TransientModel):
    _name = "sap.pl.outstanding.comment.wizard"
    _description = "PL Manual Outstanding Comment Wizard"
    _inherit = "sap.pl.outstanding.comment.abstract"

    # 向导专属多对多字段:使用独立关联表避免与持久模型冲突
    reconcile_comment = fields.Many2many(
        'sap.pl.outstanding.comment',
        'sn_sap_pnl_oc_wizard_reconcile_rel',
        'wizard_id',
        'comment_id',
        string='Outstanding Comment'
    )

    # 向导确认按钮逻辑示例
    def action_confirm(self):
        for record in self:
            # 将向导数据同步到持久模型
            self.env['sap.pl.outstanding.comment'].create({
                'plant_id': record.plant_id.id,
                'period_id': record.period_id.id,
                'description': record.description.id,
                # 其他字段映射...
            })
        return {'type': 'ir.actions.act_window_close'}

关键注意事项

  • 多对多字段:向导和持久模型的多对多关联必须使用不同的关系表,避免数据库表冲突。
  • 视图复用:可通过继承原模型视图快速构建向导视图,仅需调整按钮等向导专属元素。
  • 逻辑维护:所有验证规则、onchange方法、通用业务逻辑都放在抽象模型中,后续修改只需维护这一处,无需同步更新两个模型。

内容的提问来源于stack exchange,提问作者Jacky Zhang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 02:05:34