Odoo15如何实现自定义展位与event.booth的One2one关联
Odoo 15 自定义展位与event.booth一对一关联实现方案
Odoo全版本均未提供原生fields.One2one字段类型,官方标准的一对一关系实现方案为「多对一字段+数据库级唯一约束+反向关联计算字段」,完全满足双向唯一对应的业务规则,具体实现步骤如下:
1. 自定义展位模型添加核心关联字段
在你的自定义展位模型中,新增指向官方event.booth模型的Many2one字段,同时配置数据库唯一约束,从存储层保证关联关系唯一:
from odoo import models, fields, api from odoo.exceptions import ValidationError class EventBoothCustom(models.Model): _name = 'event.booth.custom' _description = '自定义展会展位' # 关联官方event.booth的核心字段 event_booth_id = fields.Many2one( comodel_name='event.booth', string='关联官方展位', required=True, index=True, # 级联规则按业务选:cascade=删官方展位自动删自定义展位;restrict=有自定义展位时禁止删官方展位 ondelete='cascade' ) # 数据库层面唯一约束,彻底杜绝重复关联 _sql_constraints = [ ( 'uniq_event_booth', 'unique(event_booth_id)', '每个官方展位仅能绑定一条自定义展位记录' ) ] # ORM层前置校验,提前拦截重复关联请求,优化报错提示 @api.constrains('event_booth_id') def _check_event_booth_uniq(self): for record in self: duplicate = self.search( [('event_booth_id', '=', record.event_booth_id.id), ('id', '!=', record.id)], limit=1 ) if duplicate: raise ValidationError( f"官方展位「{record.event_booth_id.display_name}」已绑定其他自定义展位,不可重复关联" )
2. 继承官方event.booth模型添加反向关联
反向关联不需要额外存储数据,用计算字段自动匹配对应的自定义展位即可,因为正向已经加了唯一约束,反向查询永远只会返回0或1条结果,不会出现数据冲突:
class EventBooth(models.Model): _inherit = 'event.booth' custom_booth_id = fields.Many2one( comodel_name='event.booth.custom', string='关联自定义展位', compute='_compute_custom_booth', readonly=True ) def _compute_custom_booth(self): # 批量查询优化,避免循环单条查库拖慢性能 custom_booth_map = { line.event_booth_id.id: line for line in self.env['event.booth.custom'].search([('event_booth_id', 'in', self.ids)]) } for booth in self: booth.custom_booth_id = custom_booth_map.get(booth.id, False)
可选扩展配置
- 如果需要在官方展位的表单页直接编辑自定义展位信息,可以给
custom_booth_id字段添加inverse反向写入方法,实现双向编辑,记得在写入逻辑里补充唯一性校验即可。 - 如果需要在官方展位列表/搜索视图里按自定义展位属性筛选,可以将自定义展位的常用字段设为
related关联字段,挂在event.booth模型上直接使用,不需要重复存储数据。 - 不要尝试用两个互相关联的
Many2one字段实现一对一,会产生数据冗余,还容易出现两边关联ID不一致的脏数据问题。
内容的提问来源于stack exchange,提问作者unnamed-dev
相关产品推荐
相关产品推荐

