在 Odoo 模型设计中,Many2one字段用于建立表间的关联关系,而ondelete属性则决定了当被关联记录(主记录)被删除时,当前记录(关联记录)的处理方式。通过具体模型示例,详解ondelete的三种常见策略:restrict、set null和cascade,帮助开发者根据业务需求选择合适的关联删除逻辑。
一、模型示例:项目与明细行的关联
我们以两个模型为例:
项目主表(edoproject.project):通过One2many字段关联多个明细行
项目明细行表(edoproject.projectmx):通过Many2one字段关联主项目,并设置ondelete策略
项目主表
class EdoProject_Project(models.Model):
_name = "edoproject.project"
_description = "项目档案"
projectmx_ids = fields.One2many(
'edoproject.projectmx', # 关联的明细行模型
'pinban_id', # 明细行中的外键字段(即projectmx模型中的反向关联字段)
string='明细记录'
)
项目明细行表
class EdoProject_Projectmx(models.Model):
_name = "edoproject.projectmx"
_description = '项目明细行'
project_id = fields.Many2one(
'edoproject.project', # 关联的主项目模型
string='项目ID',
ondelete="restrict" # 重点:设置删除策略
)
二、ondelete 策略详解
1. ondelete="restrict"(默认策略,限制删除)
效果:当主项目记录(edoproject.project)存在关联的明细行时,禁止删除主记录。
Odoo 会抛出错误提示:Cannot delete record because it is referenced by other records,并阻止删除操作。
适用场景:
当需要严格保证数据完整性,不允许删除仍有依赖记录的主数据时使用(例如:禁止删除仍有订单的客户)。
代码示例:
project_id = fields.Many2one('edoproject.project', string='项目ID', ondelete="restrict")
操作演示:
若主项目存在projectmx_ids明细行,直接删除主项目会触发 Odoo 的完整性校验,操作失败。
2. ondelete="set null"(置空外键)
效果:删除主项目时,自动将所有关联的明细行的project_id字段设置为NULL(空值)。
需注意:明细行的project_id字段必须允许NULL(即required=False,默认允许),否则会报错。
适用场景:
当允许明细行在主项目删除后独立存在(如历史记录归档),但需断开关联关系时使用。
代码示例:
project_id = fields.Many2one('edoproject.project', string='项目ID', ondelete="set null")
操作演示:
删除主项目后,查询明细行表会发现project_id字段值变为NULL,明细行仍保留在数据库中。
3. ondelete="cascade"(级联删除)
效果:删除主项目时,自动级联删除所有关联的明细行记录。
这是最 “激进” 的策略,主记录与关联记录会被同时删除。
适用场景:
当关联记录完全依赖主记录存在(如订单与订单项),主记录删除时关联数据失去意义时使用。
代码示例:
project_id = fields.Many2one('edoproject.project', string='项目ID', ondelete="cascade")
操作演示:
删除主项目后,对应的projectmx_ids明细行会被自动删除,数据库中不再存在相关记录。
三、注意事项
默认策略:若不显式设置ondelete,Odoo 默认使用restrict策略,确保数据不被意外删除。
字段约束:使用set null时,需确保Many2one字段允许NULL(即未设置required=True),否则 Odoo 会因无法置空而报错。
业务逻辑一致性:
选择策略时需结合业务规则,例如:
财务系统中,禁止删除有凭证的科目(用restrict);
日志系统中,允许日志在来源删除后保留(用set null);
订单系统中,订单删除时同步删除订单项(用cascade)。