在Odoo 17中创建插件卸载后数据仍保留的字段
Odoo 字段持久化需求:ORM正常使用但卸载插件后保留数据
需求说明
- 希望Odoo ORM能像普通字段一样处理自定义字段,但不控制数据库列
- 此前将模型扩展打包为插件,卸载时Odoo会删除插件定义的字段(含数据库列及对应数据),不符合业务需求
- 核心目标:字段在UI和ORM中正常工作,卸载插件后数据完整保留,实现系统优雅降级
当前实现方式
绕过Odoo常规fields.X声明,在_auto_init()方法中动态创建字段:
# @api.model # Odoo 17已弃用,可移除 def _auto_init(self): res = super()._auto_init() # 幂等创建数据库列,确保列存在 self._cr.execute("ALTER TABLE res_partner ADD COLUMN IF NOT EXISTS x_customer_flag boolean") # 仅当字段未注册时,创建ir.model.fields记录 model = self.env['ir.model'].search([('model', '=', 'res.partner')], limit=1) if not self.env['ir.model.fields'].search([('model_id', '=', model.id), ('name', '=', 'x_customer_flag')]): self.env['ir.model.fields'].create({ 'name': 'x_customer_flag', 'model_id': model.id, 'field_description': 'Customer is banned from store', 'ttype': 'boolean', 'state': 'manual', # 预期可防止更新时自动删除字段 'manual': True }) return res
卸载插件时,仅删除ir.model.fields中的字段记录,保留数据库列及数据。
理想简化方案
希望采用常规fields.Boolean()声明简化代码,同时保持数据持久化,理想代码示例:
class GisResPartnerExtension(models.Model): _inherit = 'res.partner' x_customer_flag = fields.Boolean(string="Customer is banned", manual=True) # 注:manual=True为虚构参数 def _auto_init(self): res = super()._auto_init() # 按需幂等创建数据库列(非破坏性) return res
但manual=True并非真实可用参数,且字段自带的manual标识作用不明确,因此寻求更优实现方式。
内容的提问来源于stack exchange,提问作者wz2b
相关产品推荐
相关产品推荐

