第十一章 数据文件
篇别:第一篇 基础知识
本章学习目标
- 能编写 XML 数据文件(
record、function、delete)并理解 加载顺序 对ref的影响。 - 能维护
ir.model.access.csv等 CSV 数据 并处理 编码与列规范。 - 能根据场景选择
noupdate策略,并解释升级时「改了 XML 却不生效」的原因。 - 能区分
data与demo,并在生产、CI、培训环境中正确启用演示数据。
导读:数据文件在模块中的角色
模块不仅包含 Python 与视图,还通过 XML/CSV/YML(少见) 向数据库注入 元数据与种子数据:序列、权限、菜单、默认配置等。安装与升级时,框架按 __manifest__.py 中 data / demo 列表顺序 加载这些文件。理解 ir.model.data(外部 ID) 与 noupdate 是避免「环境不一致」的关键(详见第六章)。
11.1 XML 数据文件
11.1.1 知识要点
| 元素 | 作用 |
|---|---|
<record> |
创建或更新一条业务记录;id 生成 XML ID |
<field> |
字段值;可用 eval 执行 Python 表达式 |
<function> |
调用模型方法,适合复杂初始化 |
<delete> |
按 id 或 search 删除(生产慎用) |
常用 field 写法:
- 文本:
<field name="name">值</field> - 引用:
<field name="model_id" ref="model_library_book"/> - 布尔:
<field name="active" eval="True"/> - 多对多:
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/> - 一对多子表:嵌套
<record>或使用function创建
11.1.2 案例
案例 A:序列
<record id="seq_library_book" model="ir.sequence">
<field name="name">图书编号</field>
<field name="code">library.book</field>
<field name="implementation">standard</field>
<field name="prefix">B</field>
<field name="padding">5</field>
<field name="number_next">1</field>
</record>
案例 B:在模型上调用 function
<function model="library.book" name="action_rebuild_default_codes">
<value eval="[]"/>
</function>
方法需 @api.model 且接受参数列表;具体签名以实现为准。
案例 C:按 domain 删除(仅开发/迁移)
<delete model="library.book" search="[('active','=',False)]"/>
风险:误删生产数据;务必 先在副本验证,并考虑 备份。
11.1.3 截图占位


11.1.4 本节练习
- 实操:用 XML 创建 3 条 默认图书记录(
name、isbn),并保证第二次升级 不重复插入(提示:固定id的record会更新同一条)。 - 简答:同一文件内后面的
record能否ref前面定义的id?跨文件呢? - 判断:
<delete search="..."/>在每次-u都会执行删除。( )
参考答案提示:2. 同模块同次加载顺序内可以;跨文件取决于 manifest 中文件顺序。3. 对,每次升级若仍匹配 domain 会删,极危险。
11.2 CSV 数据文件
11.2.1 知识要点
- 首行:字段名,须与模型 完全一致(或 CSV 约定列)。
id列:module.name形式定义 外部 ID,如my_library.access_book_user。model_id:id等:id后缀:指向另一条 CSV/XML 行的 外部 id,加载器自动解析为整数。- 编码:UTF-8(无 BOM 或统一约定);Excel 另存需注意。
- 换行与引号:字段内含逗号时需正确引号包裹。
11.2.2 案例
案例 A:访问权限 CSV
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_library_book_user,library.book.user,model_library_book,base.group_user,1,1,1,0
案例 B:从界面导出再改
设置 → 技术 → 模型访问权限 → 导出 → 增删行 → 放回模块 security/ → 升级。
11.2.3 截图占位


11.2.4 本节练习
- 简答:CSV 加载失败常见 5 种原因?
- 实操:故意删掉 CSV 首行一列名,记录完整报错。
- 简答:为何
ir.model.access常用 CSV 而很少用纯 XML?
参考答案提示:1. 编码、列名、ref 不存在、重复 id、布尔/整数格式错误。3. 行多、 diff 清晰、团队习惯。
11.3 data 与 noupdate
11.3.1 知识要点
<odoo noupdate="1">:块内通过 XML ID 匹配到的记录,在 模块升级 时可能 不再用文件内容覆盖 已有字段(用户自定义保留)。noupdate="0"或默认:升级时 同步 XML 中的字段值(仍受字段与模型逻辑约束)。- 痛点:你以为改了 XML,升级后界面没变 → 可能是 noupdate 或 用户已改库内记录。
- 破解(慎用):删
ir.model.data对应行、改 XML id、用迁移脚本 SQL 更新。
11.3.2 案例
<odoo noupdate="1">
<record id="library_default_max_days" model="ir.config_parameter">
<field name="key">library.default_max_days</field>
<field name="value">14</field>
</record>
</odoo>
说明:用系统参数演示 noupdate;业务上也可在 res.config.settings 的扩展字段中写 config_parameter(见第八章 8.13)。
11.3.3 截图占位

11.3.4 本节练习
- 判断:
noupdate=1时永远不能再改该记录。( ) - 实操:对某
noupdate=1记录在界面改一个字段,再-u模块,观察该字段是否被 XML 改回。 - 简答:哪些数据适合
noupdate=1?哪些必须0?
参考答案提示:1. 错。3. 用户可配默认适合 1;法规强制结构适合 0 或由迁移脚本改。
11.4 演示数据(新增)
11.4.1 知识要点
demo:__manifest__.py中独立列表,常在 创建数据库勾选「加载演示数据」 时安装;生产库 勿依赖。- 趋势:演示数据 默认不进入生产;培训环境可单独建库启用。
- CI:测试若依赖 demo 数据,需在流水线中 显式安装带 demo 的库 或 在测试里 create。
11.4.2 案例
# __manifest__.py
'demo': [
'demo/library_demo.xml',
],
<!-- demo/library_demo.xml -->
<odoo noupdate="1">
<record id="demo_book_1" model="library.book">
<field name="name">演示图书一</field>
<field name="isbn">DEMO-001</field>
</record>
</odoo>
noupdate 可防止演示库被升级反复重置(按需)。
11.4.3 截图占位

11.4.4 本节练习
- 简答:为何生产库不建议加载 demo?
- 情景:销售演示前需要「像真的一样」的数据,如何既不污染生产又不手写 XML?
参考答案提示:2. 独立演示库、neutralize 副本、或导入专用 SQL/模块。
11.5 数据加载调试清单
| 现象 | 检查项 |
|---|---|
| ParseError | XML 语法、标签闭合、特殊字符转义 |
| External ID not found | ref、depends、文件顺序 |
| 升级无变化 | noupdate、是否改错模块/数据库 |
| CSV 乱码 | UTF-8、Excel 保存格式 |
11.5.1 截图占位

11.5.2 本节练习
- 实操:用
-u my_module --log-level=debug截取一段数据加载日志并标注文件名顺序。
本章综合练习
- 编写
<function>:升级时为所有default_code为空 的图书调用模型方法生成编码(方法内用序列)。 - 风险分析:
<delete model="library.loan" search="[('state','=','draft')]"/>在生产使用的 前置条件(备份、停机、验证 SQL 条数等)。 - 设计:同一配置项既要 首次安装默认值 又要 允许用户永久覆盖,如何用
noupdate+ 单独config_parameter表达? - 拓展:阅读官方 Manifest 文档中关于
data/post_load的说明,一句话记录差异。
本章对应白皮书目录:第十一章 数据文件。