Odoo模块安装时,如何先加载OrderStage数据再添加res_config_settings字段?
Odoo模块安装:解决res_config_settings必填字段NOT NULL错误
错误原因
模块安装时,Odoo的执行顺序是先创建所有模型字段(包括你扩展res_config_settings添加的default_order_stage_id),再加载XML预加载数据。这时候添加必填字段时,order.stage的预加载数据还未导入,系统无法找到有效默认值填充字段,触发Table 'res_config_settings': unable to set NOT NULL on column 'default_order_stage_id'错误。
可行解决方案
方案一:用post_init_hook延迟添加必填字段
- 暂时修改
res_config_settings的字段定义,去掉required=True(或者先不添加该字段)。 - 在模块中编写安装后钩子函数,待
order.stage数据加载完成后,再添加字段并设置NOT NULL约束与默认值:from odoo import api, SUPERUSER_ID def post_install_set_default_stage(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) # 获取预加载的默认订单阶段 default_stage = env['order.stage'].search([], limit=1) if not default_stage: return # 添加字段并设置约束与默认值 cr.execute(""" ALTER TABLE res_config_settings ADD COLUMN IF NOT EXISTS default_order_stage_id INTEGER REFERENCES order_stage(id) NOT NULL DEFAULT %s """, (default_stage.id,)) # 确保现有记录都赋值 cr.execute(""" UPDATE res_config_settings SET default_order_stage_id = %s WHERE default_order_stage_id IS NULL """, (default_stage.id,)) - 在模块的
__manifest__.py中注册钩子:'post_init_hook': 'post_install_set_default_stage', - 后续升级模块时,钩子只会在首次安装时执行,无需重复修改。
方案二:拆分模块分离依赖
把order.stage模型及预加载数据拆成独立的基础模块,先安装这个基础模块,再安装包含res_config_settings扩展的模块。这样安装第二个模块时,order.stage的数据已经存在,系统能正常找到默认值,直接添加必填字段不会报错。
方案三:临时允许为空,安装后再修正约束
- 先将字段设为非必填:
default_order_stage_id = fields.Many2one('order.stage', required=False, string='Default Order Stage') - 安装模块,此时字段允许为空,不会触发错误。
- 进入系统后,手动设置默认订单阶段,或用脚本批量更新所有配置记录:
(可把这个函数注册为from odoo import api, SUPERUSER_ID def update_default_stage(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) default_stage = env['order.stage'].search([], limit=1) env['res.config.settings'].search([]).write({'default_order_stage_id': default_stage.id})post_init_hook,或手动执行) - 把字段改回
required=True,升级模块,此时所有记录已有有效值,系统能成功添加NOT NULL约束。
内容的提问来源于stack exchange,提问作者David Côté-Tremblay
相关产品推荐
相关产品推荐

