Odoo 10更新模块时为何删除仍存在对应XML ID的模块导入数据记录
问题描述
我在Odoo 10中恢复了一个数据库,同时从原服务器复制了对应实例的源代码和virtualenv环境,恢复流程正常,数据库可正常操作。
但我尝试更新所有模块时,部分模块更新触发严重错误。仅更新l10n_es模块时,出现如下报错:
odoo.addons.base.ir.ir_model: Deleting 24@account.account.type (l10n_es.account_type_ingresos_neto)
odoo.sql_db: bad query: DELETE FROM account_account_type WHERE id IN
(24) ...
NotNullViolation: null value in column "user_type_id" violates
not-null constraint DETAIL: Failing row contains (712, null, other,
Beneficios en activos financieros disponibles para la venta, 1, f, 1,
1, null, 900000000, 2018-02-01 09:28:54.453977, null, 2018-02-01
09:28:54.453977, null, f). CONTEXT: SQL statement "UPDATE ONLY
"public"."account_account" SET "user_type_id" = NULL WHERE $1
OPERATOR(pg_catalog.=) "user_type_id""
更新前我执行了如下查询:
SELECT * FROM ir_model_data WHERE model='account.account.type' AND res_id=24;
返回结果:
id | create_uid | create_date | write_date | write_uid | noupdate | name | date_init | date_update | module | model | res_id ------+------------+----------------------------+----------------------------+------------+----------+----------------------------+---------------------+---------------------+---------+----------------------+-------- 7850 | 1 | 2018-02-01 09:19:01.412377 | 2021-02-08 15:28:04.013464 | 1 | f | account_type_ingresos_neto | 2018-02-01 09:19:01 | 2021-02-08 15:28:04 | l10n_es | account.account.type | 24
随后我又执行了查询:
SELECT * FROM account_account_type WHERE id=24;
返回结果:
id | create_uid | name | write_uid | note | write_date | create_date | include_initial_balance | type ----+------------+--------------------------+-----------+------+----------------------------+----------------------------+-------------------------+------- 24 | 1 | Ingresos patrimonio neto | 1 | | 2021-02-08 15:28:04.013464 | 2018-02-01 09:19:01.412377 | t | other
通过这两条查询我确认,数据库中存在ID为24、名为Ingresos patrimonio neto的账户类型,其对应的External XML ID为l10n_es.account_type_ingresos_neto。
我核查了实例代码,l10n_es模块的data目录下存在account_type.xml文件,该文件已在__manifest__.py中声明引入,文件内定义了该条记录的创建逻辑:
<record id="account_type_ingresos_neto" model="account.account.type"> <field name="name">Ingresos patrimonio neto</field> <field name="include_initial_balance" eval="True"/> </record>
因此我无法理解为何更新模块时系统会删除这条记录(该删除操作直接触发了上述报错):
odoo.addons.base.ir.ir_model: Deleting 24@account.account.type (l10n_es.account_type_ingresos_neto)
我此前认知中,模块更新时仅会删除数据库中对应XML ID在当前模块代码中已不存在的模块导入记录,请问为何模块更新时会删除代码中仍存在对应XML ID的已有记录?
问题根因
这个现象是Odoo 10及更早版本模块更新逻辑的已知特性,核心触发原因有3种:
- 你查询到
ir_model_data里该记录的noupdate字段值为f(即允许更新),但模块更新时Odoo会先扫描当前模块所有声明加载的XML文件中的XML ID,生成待保留的ID列表,再删除数据库中属于该模块、但不在待保留列表里的记录。你之所以明明代码里有对应的ID还被删,大概率是account_type.xml在__manifest__.py中的加载声明加了noupdate="1"属性,当XML文件被标记为noupdate加载时,Odoo更新模块时不会把文件里的XML ID加入待保留列表,所以即使文件里有对应定义,系统还是会判定该ID在代码中不存在,触发删除。 - 第二个可能原因:你当前代码里的
account_type.xml中该record定义缺少必填字段type(你数据库里该记录的type值是other,但你贴的XML代码里没有定义这个字段),Odoo会判定该record定义无效,没有加入待保留列表,进而触发删除。 - 第三个可能原因:恢复数据库后你没有更新模块列表就直接执行了模块更新,Odoo缓存的模块数据文件列表还是旧的,没有识别到
account_type.xml里的ID。
修复方案
- 先执行以下SQL修改该记录的
noupdate属性,禁止Odoo自动删除:
UPDATE ir_model_data SET noupdate = 't' WHERE module = 'l10n_es' AND name = 'account_type_ingresos_neto';
- 补全
account_type.xml中该record的type字段定义:
<record id="account_type_ingresos_neto" model="account.account.type"> <field name="name">Ingresos patrimonio neto</field> <field name="include_initial_balance" eval="True"/> <field name="type">other</field> </record>
- 先刷新模块列表,再重新更新
l10n_es模块即可。
内容的提问来源于stack exchange,提问作者forvas

