Odoo委托继承中删除partner_id字段遇外键冲突求助
我定义了如下自定义模型:
class Customer(models.Model): _name = "my_module.customer" _inherits = {"res.partner": "partner_id"} partner_id = fields.Many2one(comodel_name="res.partner", ondelete="restrict", required=True) # more fields...
数据库中已存在该模型及关联的res.partner记录,且这些res.partner记录同时关联了门户用户(res.users)。
现在想要删除该自定义模型中的partner_id字段,但升级模块时出现如下外键违反错误:
psycopg2.errors.ForeignKeyViolation: update or delete on table "res_partner" violates foreign key constraint "res_users_partner_id_fkey" on table "res_users"
我理解该错误是因为res.partner记录仍被res.users引用,但不明白为何Odoo要尝试删除与my_module.customer关联的res.partner记录,而非仅解除关联并删除partner_id列?使用委托继承时Many2one字段的行为是否有差异?
请问如何在保留res.partner和res.users记录的前提下,成功删除my_module.customer中的partner_id字段?
原因分析
Odoo的**委托继承(_inherits)**有特殊逻辑:子模型和父模型是强绑定关系,当你删除作为继承关联的Many2one字段时,Odoo会默认尝试级联删除关联的父模型(res.partner)记录——这是因为委托继承的设计逻辑是子模型依赖父模型存在,解除继承绑定(删除关联字段)时,Odoo会认为父模型记录不再被需要,从而触发删除操作,而你的res.partner又被res.users引用,所以触发外键冲突。这是委托继承特有的行为,和普通Many2one字段的删除逻辑完全不同。
分步解决方案
要保留res.partner和res.users记录,必须分两步操作:
第一步:解除委托继承,保留partner_id字段
修改模型代码,移除_inherits配置,但暂时保留partner_id字段,把它当成普通Many2one字段处理:
class Customer(models.Model): _name = "my_module.customer" # 移除_inherits配置 partner_id = fields.Many2one(comodel_name="res.partner", ondelete="restrict", required=True) # more fields...
升级模块,此时Odoo会解除委托继承的绑定关系,不会删除res.partner记录。
第二步:删除partner_id字段
确认第一步升级成功后,再修改代码删除partner_id字段:
class Customer(models.Model): _name = "my_module.customer" # 移除partner_id字段 # more fields...
再次升级模块,此时Odoo只会删除my_module_customer表中的partner_id列,不会触发res.partner的删除操作,自然不会和res.users的外键约束冲突。
内容的提问来源于stack exchange,提问作者Seaworn

