在Odoo中如何全局校验模型关联字段的公司ID一致性?
Odoo全局实现公司一致性校验方案
要实现你提出的「所有带自身company_id且关联模型也有company_id的模型,自动校验双方公司一致」的需求,最优雅的方式是用Mixin抽象类+自动字段检测,无需在每个模型重复编写校验逻辑,具体实现如下:
1. 编写通用校验Mixin
创建一个抽象模型,把校验逻辑封装为可复用的Mixin,所有需要该功能的模型都能直接继承:
from odoo import models, api, _ from odoo.exceptions import ValidationError class CompanyConsistencyMixin(models.AbstractModel): _name = 'company.consistency.mixin' _description = '全局公司一致性校验Mixin' @api.model def _get_related_company_fields(self): # 自动识别当前模型中,关联带`company_id`的Many2one字段 return [ field_name for field_name, field in self._fields.items() if field.type == 'many2one' and 'company_id' in self.env[field.comodel_name]._fields ] @api.constrains('company_id') def _check_company_on_self_change(self): # 当自身`company_id`修改时,校验所有关联字段的公司一致性 self._validate_company_matches() @api.constrains() def _check_company_on_related_change(self): # 当关联字段修改时,触发公司一致性校验 fields_to_check = self._get_related_company_fields() if fields_to_check: self._validate_company_matches(fields_to_check) def _validate_company_matches(self, fields_to_check=None): fields_to_check = fields_to_check or self._get_related_company_fields() for field_name in fields_to_check: field = self._fields[field_name] for rec in self: # 仅当当前记录有公司、且关联记录存在时执行校验 if rec.company_id and rec[field_name]: if rec.company_id.id != rec[field_name].company_id.id: raise ValidationError(_( "字段「%(field)s」关联的%(model)s「%(rel_name)s」公司不匹配!\n" "当前记录公司:%(curr_comp)s\n关联记录公司:%(rel_comp)s" ) % { 'field': field.string or field_name, 'model': field.comodel_name, 'rel_name': rec[field_name].display_name, 'curr_comp': rec.company_id.name, 'rel_comp': rec[field_name].company_id.name })
2. 让目标模型继承Mixin
以res.partner为例,只需继承这个Mixin就能自动生效校验:
class ResPartner(models.Model): _inherit = ['res.partner', 'company.consistency.mixin']
其他任何符合条件的模型(比如account.move、purchase.order这类自带company_id且关联模型也有company_id的),只要继承该Mixin,就会自动启用公司一致性校验,无需额外编写重复逻辑。
方案优势
- 全局复用:一次编写,所有符合条件的模型都能直接套用,避免重复造轮子
- 自动适配:Mixin会自动识别模型内的关联字段,无需手动指定要校验的字段
- 精准触发:仅在
company_id或关联字段修改时执行校验,不会额外消耗系统性能 - 清晰提示:报错信息明确指出问题字段、关联记录及双方公司,用户可快速排查
内容的提问来源于stack exchange,提问作者Shoaib Ahmed
相关产品推荐
相关产品推荐

