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
相关产品推荐
相关产品推荐

