导入向导

Odoo 导入向导为什么总能猜对列:mapping suggestion、预览和批量落库链路

从预览、字段猜测到真正落库,拆开看 base_import 如何把一份外部文件变成可导入的 ORM 数据。

Odoo 开发 框架
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

导入向导的目标不是“读文件”,而是“把外部列变成 Odoo 字段”

base_import 最容易被低估的地方,是它并不只是一个 CSV 上传器。 它真正做的事,是把一份外部文件逐步变成 ORM 能理解的数据矩阵。

所以它要解决的问题其实有三个:

  • 这份文件有哪些列?
  • 每一列最像哪个 Odoo 字段?
  • 真的落库前,数据格式和结构有没有问题?

这就是为什么导入向导会先预览,再建议映射,最后才执行导入。

预览阶段先看字段树,再看前几行数据

parse_preview() 的第一步是 get_fields_tree()。 这一步不是随便列出模型字段,而是递归地整理出“可导入字段树”,包括:

  • 普通字段
  • many2one / many2many 的子字段
  • o2m 的递归层级
  • 哪些字段实际上不能导入

接着它会读文件、取前几行预览,并根据列里的内容估计类型。 这一步很重要,因为字段匹配不是只看列名,还要看列值像不像日期、数字、关系 ID。

换句话说:

Odoo 不是先猜名字,再看数据;它是名字和数据一起看。

字段建议的顺序非常讲究

_get_mapping_suggestion() 的规则可以记成一个三段式:

  1. 先看用户以前存过的映射 如果同一个外部系统经常导入,旧映射会直接复用。

  2. 再做精确匹配 先比技术名,再比字段 label,再比英文 label 或翻译后的 label。

  3. 最后才做模糊匹配 用字符串距离去找最接近的字段,而且会先根据列值类型过滤掉明显不可能的字段。

这也是导入向导看起来“很聪明”的原因: 它不是靠一个规则,而是靠一层层缩小候选集。

对关系字段,lead_id/description 这种斜杠路径会被拆成层层匹配: 先找 lead_id,再在它的子字段里找 description。 这就是导入多层关联时最实用的语法。

真正落库前,先把稀疏映射压成密集矩阵

execute_import() 干的核心工作,和 UI 没什么关系,和数据结构关系最大。

它会先把“哪些列要导入”整理成一份连续字段列表,再把每一行数据裁成同样的结构。 这么做是为了让 model.load() 能直接消费。

然后它会依次处理:

  • 日期、时间、浮点等格式解析
  • 二进制图片文件名提取
  • 多列映射到同一个字段时的合并
  • fallback value 的兜底逻辑

最后才把数据交给 ORM 的 load()。 这意味着,真正的写入不是导入向导自己完成的,而是复用 Odoo 一贯的数据加载通道。

这一点很重要,因为它保证了:

  • 默认值、约束、权限、计算字段仍然生效
  • 导入不是绕过 ORM 直接插数据库
  • 导入和普通创建/写入的语义尽量一致

为什么导入支持 dry-run

execute_import() 会先开 savepoint,再决定是否回滚。 这让导入向导可以做“试跑”:

  • 先跑一遍看错误
  • 不真正提交
  • 用户修正映射后再正式导入

对大批量导入来说,这是很实用的设计。 它既能提前暴露错误,又不会污染数据库。

另一个细节是:导入成功后,系统会把列名和字段映射保存到 base_import.mapping。 这样下次再导入同一类文件时,建议会更准。

实战里最该记住的 4 条

  • 列名尽量靠近技术名或字段 label,能少很多模糊匹配误差
  • 多层关系字段直接用 a/b/c 路径,不要硬拆成独立列
  • 重复导入同一外部系统时,保存过的 mapping 很值钱
  • 导入远程 URL 图片有额外权限控制,不要默认以为谁都能开

你可以把 base_import 理解成一个“把外部文件翻译成 ORM 输入”的翻译器。 它不是简单搬运,而是先理解,再转换,再提交。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。