2026/10/22 1:05:41

Odoo 17中文数据字典:从表结构到实战查询的完整指南

Odoo 17中文数据字典:从表结构到实战查询的完整指南 简介这份中文数据字典是为Odoo 17版本量身定制的数据库结构参考手册主要面向开发人员、实施顾问以及正在学习Odoo的初学者。它把原本分散在数据库中的大量数据表、字段和关系整理成一份便于查阅的PDF文档解决了直接操作数据库难以快速定位表结构的问题。资源包总共只有1个PDF文件大小为8.07MB轻巧便携既能在线浏览也适合下载后离线查看。字典内容由Navicat导出按照服务器、数据库、模式、表四个层次组织层次分明从account_account、account_account_tag等财务相关表到库存、销售等业务模块都能看到清晰的表名及字段关联有助于打通业务理解与技术实现。目前已有133人学习下载适合具备一定Odoo操作经验、想进一步掌握数据模型的用户作为常备查询工具。1. 拿到中文版 Odoo 17 数据字典先搞清这份资源能解决什么Odoo 17 数据字典已翻译为中文不是什么高深技术它就是一份把 PostgreSQL 里 Odoo 数据库的所有业务表、字段、类型、约束整理成中文表格的结构文档。第一次做 Odoo 二次开发的人最懵的往往不是 Python 模型代码而是客户问这个字段存在哪张表时对着数据库里一堆 account_ 开头的表名无从下手。这份字典能直接回答这类问题表名是什么、字段有哪些、类型是什么、哪些列是外键。适合做 Odoo 开发、实施、报表定制和数据迁移的从业者尤其是刚接手 Odoo 项目、需要快速读懂财务模块表结构的人。下面我会带你把这本字典真正翻熟从查表方法讲到实际业务链路最后给你一个不依赖第三方工具、随时生成最新字典的 SQL 方案。2. 数据字典的三层读法表名、字段、关系表怎么快速识别2.1 从表名命名规则读出模块归属Odoo 的物理表名不是拍脑袋取的。每个模型定义时Odoo 会按模块标识_模型名的规则自动建表规则是模型名里的点号转下划线、全部小写。比如 account.move 对应 account_moveaccount.payment.register 对应 account_payment_register。这个规则是读字典的第一把钥匙记住它之后字典里九成表名你都能反推出它在代码里对应的模型。翻开这份字典能发现一个明显规律account_ 前缀的表占了目录的大半。account_account 是会计科目表account_journal 是日记账account_move 是会计凭证account_payment 是付款单——这些都是 Odoo 财务模块account_accountant的核心表。更值得注意的是目录里还能看到 account_analytic_account_mrp_bom_rel 这种把财务和生产制造串起来的关系表说明导出这份字典时数据库里同时安装了 MRP 模块。表名里的 mrp 就是证据也是判断一个库装了什么模块的快速线索。从这份字典可以看出表大致分三类识别它们能省很多时间表类型命名特征典型例子业务含义业务表模块前缀_业务名字段多、有主键account_move会计凭证头关系表以 _rel 结尾字段少一般只有外键account_account_account_journal_rel科目与日记账多对多关系向导表以 _wizard 结尾临时存储数据account_payment_register付款登记向导关系表字段少一眼能认出来向导表数据用完即弃查询报表时基本不用碰它。看字典时先按这三类把表归类重点关注业务表和关系表目录就能从一堆名字变成一张地图。2.2 解读字段信息类型、NULL、默认值三列怎么看Navicat 导出的字典每个表下面会列出该表所有字段至少包含字段名、类型、是否允许 NULL、默认值、注释这几项。读字段信息时我一般按三个层次去看不会逐行读完。第一层看类型。Odoo 17 里 numeric(16,2) 十有八九是 Monetary 金额字段但真实精度与币种相关不是简单的两位小数timestamp 对应 Datetime 字段varchar(n) 对应 Char 或 Text 字段。第二层看 NULL 约束主键 id 一定非空Many2one 外键字段多数允许为空但 name、date 这类业务关键字段通常 NOT NULL。第三层看默认值比如 state 状态字段一般没有默认值靠程序写入create_date 这种审计字段默认取当前时间。拿 account_move 来说字典里你会看到这些典型字段字段名类型允许 NULL说明idint4否主键namevarchar是凭证编号保存时自动生成refvarchar是外部参考号对应客户发票号datedate是记账日期statevarchar是状态可选值在代码里定义journal_idint4是日记账外键到 account_journalpartner_idint4是业务伙伴外键到 res_partnercreate_datetimestamp是创建时间注意字典只会告诉你 state 是 varchar不会告诉你它有哪些可选值——这个要到模型源码里看 selection 定义。这是一个关键边界后面避坑部分会细说。2.3 关系表与继承字段的识别技巧关系表在字典里特别好认字段就两三个全是 int4 类型的 id比如 account_account_account_journal_rel 的结构基本就是 account_id、journal_id 两个外键加上一个 id 主键。这种表是 Many2many 字段在数据库层面的落地你在 Odoo 界面看到的一个科目支持多个日记账的配置存的就是这种关系行。另外一类容易被忽略的是继承字段。Odoo 的模型经常会继承一些混入类mixin比如 mail.thread 会带来 message_ids 相关的表mail.activity.mixin 会带来活动相关字段。落到数据库层面很多表都会有 create_uid、write_uid、create_date、write_date 这四个审计字段。字典里如果看到这种字段组合说明这张表是标准的 Odoo 业务表而不是外部程序建的表。外部程序建的裸表通常没有这些列这也是判断某张表是否由 Odoo 模型管理的依据之一。3. 把字典用起来查模型对应表、反查单据链路、认清字典边界3.1 二次开发时怎么由模型名定位物理表实际开发中遇到最多的问题就是我有个模型叫 stock.move.line它在数据库里对应哪张表记不住规则也没关系直接在数据库里跑一条 SQL 就能确认SELECT table_name FROM information_schema.tables WHERE table_schema public AND table_name stock_move_line;模型名转表名的规则很简单把模型名里的点替换成下划线去掉模块前缀中间的点最后变小写。比如 account.move.line 对应 account_move_linestock.picking 对应 stock_picking。如果模型名带了自定义模块前缀比如某公司自研模块表名就会是 模块前缀_模型名 的格式不要只拿模型名后半段去猜。查到表名之后下一步就是查字段。字典的作用在这里体现得最直接定位到表按字段说明找到目标列确认类型和约束再到模型代码里看业务逻辑。这个流程比在 pgAdmin 里一棵树一棵树点开快得多也比翻源码逐个模型找字段更高效因为字典是纯数据库视角没有代码的干扰信息。3.2 从一张业务单据反查整个数据链路字典表多的时候顺着业务单据反查链路是最高效的读法。我以一张客户发票为例演示怎么走一张发票在界面上是一个表单到了数据库里其实是多张表配合。发票主数据在 account_move 表它的 move_type 字段区分了客户发票、供应商账单、日记账分录发票的明细行在 account_move_line 表通过 move_id 关联回 account_move如果这张发票做了部分收款会产生 account_partial_reconcile 记录把 invoice 的 line 和 payment 的 line 关联起来最终付款动作发生在 account_payment 表payment 又通过 account_payment_register 向导写入。查字典时可以按这个顺序逐表看字段理解每个环节的数据落地SELECT id, name, move_type, state, journal_id, partner_id FROM account_move WHERE id 具体单据ID;这段 SQL 验证了字典里的字段是否真实可用。比较关键的是 move_type 和 state 这两个字段move_type 决定这张凭证是客户发票还是供应商账单state 决定它当前处于草稿、已过账还是已取消。但字典不会告诉你 move_type 的具体枚举值实际开发时还是得回到模型源码里确认这一点在排错时尤其容易踩坑。3.3 字典查不到的东西状态枚举、计算方法、关联逻辑数据字典是数据库结构的快照不是业务逻辑的说明。实际使用时要清楚它的三个边界。第一字段的可选值查不到。上面说的 state、move_type 这类 varchar 字段合法值定义在模型代码的 selection 属性里字典里只有varchar三个字。第二计算字段和关联字段查不到。Odoo 里很多字段是 computed 或 related 的它们不直接存在数据库里字典里没有但你在视图里能看到。第三Many2one 的显示名查不到。字典里 journal_id 是 int4但界面上显示的是日记账名称这层映射关系在模型里不在数据库里。所以这本字典的正确用法是先拿它定位表和字段再拿字段名去模型源码里看定义。把字典当索引把源码当正文两个配合用才不会一头撞进黑匣子。4. 常见问题与避坑Navicat 导出字典的五个典型陷阱4.1 字段注释一半是空的翻译对不上业务现象翻开字典很多字段的注释列是空的或者注释写得像是机器翻译比如把 move 翻成移动把 partner 翻成合作伙伴而不是业务伙伴。原因Navicat 生成数据字典时注释来源是 PostgreSQL 里的 COMMENT ON COLUMN 语句。但 Odoo 建表时字段注释并不来自模型里的 string 属性而是默认不写数据库注释。所以字典里能看到的注释要么是数据库里确实写了 COMMENT要么是导出工具从别处抓的空注释是常态翻译不准是另一层问题——move在会计语境下是凭证/分录不是移动。解决遇到不理解的中文注释先定位到模型源码里看字段的 string 和 help 属性。另一个通用做法是查官方英文术语表把字段名和标准翻译对齐。字典只能当参考索引不要逐字相信注释的准确性。4.2 建表语句里找不到外键关系全靠字段名猜现象用字典视图看表结构发现很多 int4 字段并没有外键约束。比如 account_move_line 里的 move_id理论上应该指向 account_move.id但字典里可能没有 FOREIGN KEY 记录。原因Odoo 的 ORM 层处理关系Many2one 字段在数据库层面默认不建物理外键约束尤其是大表之间。这是 Odoo 有意的设计为了减少数据库锁竞争、提升写入性能。Navicat 不会自己补外键所以导出来的字典就是有字段、没外键的骨架。解决做表关联时不要等数据库告诉你关系直接按命名规则推断——xxx_id 基本指向 xxx 表。account_move_line.move_id 就是指向 account_move。如果你需要可视化 ER 图推荐用 pgAdmin 的图形化解释或者 DataGrip 的导出功能手动补上关系再画图。最笨但最可靠的办法还是先看模型代码里的字段定义确认指向哪个模型再回到字典里验证。4.3 目录里的表比标准 Odoo 多容易看花眼现象对照官方文档或网上的 Odoo 17 表结构发现字典里多了不少关联表比如 account_analytic_account_mrp_bom_rel、account_analytic_account_mrp_production_rel。原因这份字典对应的数据库不单单是标准财务模块还安装了 MRP 生产制造模块、以及财务与分析模块的桥接扩展。模块间通过 Many2many 关系互相引用就会生成这种跨模块的 _rel 表。解决先确认自己项目的模块安装情况。如果你的项目没装 MRP这些表就不会存在也不需要关心反之如果你要开发制造相关的报表这些关联表恰恰是关键。我的习惯是拿到字典先翻目录把不认识的表名按模块归类归类不上的再单独查模型来源不要被无关的表分散注意力。4.4 小版本升级后字段对不上照抄字典直接翻车现象字典里 account_move 表有某个字段代码里也写了但生产环境跑查询报column does not exist。原因Odoo 17 的 .0 大版本下还有若干小版本升级模块时可能新增字段或重命名字段。这份字典的生成日期是 2024 年 8 月如果你手上的数据库比它新或比它旧表结构存在细微差异是完全正常的。升级过程中 Odoo 会自动执行 ALTER TABLE 加列但字典不会跟着自动更新。解决字典只能作为起点不能在开发环境直接照搬。我的标准流程是先跑一条 SQL 验证目标表的真实结构再决定查询怎么写。这个验证动作只需要几秒但能避免把半天时间耗在一个根本不存在的字段上。生产库变更前也一定要拿实际库导出的最新结构做比对。4.5 同一张表在不同模块里的含义不同现象查 account_analytic_line 表发现里面既有项目工时数据又有采购关联行的分析数据看起来特别乱。原因Odoo 的分析分录表被多个模块复用。account_analytic_line 是分析会计的行表MRP 的报工、项目的工时、采购的费用都会往里写数据靠字段组合区分业务来源字典里不会标注这种一表多义的情况。解决使用这类公共表时先确认业务上下文。比如要查项目工时就结合 task_id、project_id 字段过滤要查生产成本就结合 production_id 过滤。字典在这时候的价值是帮你看到全部字段至于怎么组合过滤条件需要你对业务模块有整体理解。拿不准时去模型源码里看字段注释比猜靠谱得多。5. 财务模块表结构实战从 account_move 到对账与付款5.1 会计凭证头表 account_move 的骨架解读account_move 是财务模块最核心的表之一界面上看到的客户发票、供应商账单、银行日记账分录底层都在这张表里靠 move_type 区分。字典里这张表的字段很多但按职责可以分成四组。第一组是审计字段id、create_date、write_date、create_uid、write_uid这些基本不用管。第二组是单据标识name 是凭证编号ref 是外部参考号narration 是说明文本。第三组是业务关键字段date 记账日期、state 状态、journal_id 日记账、partner_id 业务伙伴、company_id 公司。第四组是金额汇总字段amount_total、amount_untaxed以及对应的税合计。注意这些金额字段在数据库里都是 numeric但精度由币种决定做报表汇总时要留意 round 规则不要直接用浮点运算。state 字段在这张表里特别值得关注。Odoo 17 中凭证的状态流转是 draft草稿→ posted已过账→ cancel已取消部分单据还有 paid已付款或 reconciled已对账这种状态但它不是简单的状态机而是多个字段组合表达的结果。字典里 state 只是 varchar(16)真正判断一张发票是否已付款往往要看 account_move_line 的 reconciled 字段而不是 account_move 自己的 state。5.2 明细行 account_move_line真正写数据的表如果说 account_move 是单据头那 account_move_line 就是单据体。每张发票的每一行产品、每个税额、每笔运费都会在 account_move_line 里生成一行或多行记录。这张表的字段比头表更多也更接近记账底层。核心字段包括move_id 指向所属凭证account_id 是会计科目外键到 account_accountpartner_id 业务伙伴product_id 产品quantity 数量price_unit 单价debit 和 credit 是借贷金额一行的 debit 和 credit 有且只有一个非零balance 是净额等于 debit 减 creditamount_currency 是外币金额tax_ids 是关联的税。这组字段组合起来就能还原一张发票的完整会计分录。做报表查询时我几乎总是从 account_move_line 出发而不是从 account_move 出发。因为所有金额都在明细行上凭证头只有汇总数明细行才是联查科目、伙伴、产品的入口。字典里 account_move_line 的字段列表就是你的联查候选清单。5.3 对账与付款的流转中间表帮你串起资金链路对账是财务模块里最容易绕晕的部分字典能帮你把链路捋直。一张发票从开出到核销数据库里大致经历这样几个节点-- 发票过账后明细行进入未对账状态 SELECT id, move_id, account_id, debit, credit, reconciled FROM account_move_line WHERE move_id 目标凭证ID; -- 收到客户付款后生成 payment 并做部分核销 SELECT pl.id, pl.move_id, st.line_id, st.amount FROM account_partial_reconcile st JOIN account_move_line pl ON pl.id st.debit_move_id WHERE st.credit_move_id 付款行ID;这段 SQL 演示了 account_partial_reconcile 的典型用法它用 debit_move_id 和 credit_move_id 分别关联应收行和实收行amount 字段存放本次核销金额。一张发票如果被分两次收款就会产生两行 partial_reconcile 记录全部核销后相关明细行的 reconciled 字段变为 true。账务核销完成后如果还需要追溯银行到账就得再看 account_bank_statement_line 和 account_payment 的关联。字典里 account_payment 表有 payment_type、partner_type、amount 这些字段配合 account_bank_statement_line 的 statement_id能把客户付了多少钱、进了哪个银行账户、核销了哪张发票完整串起来。对做资金报表的开发者来说这条表链路比在界面上点来点去效率高得多。6. 进阶技巧不依赖第三方工具用 SQL 生成自己的实时中文字典Navicat 导出的字典有个硬伤它是一份静态快照数据库一变就得重新导。其实 PostgreSQL 的系统表里就存着全部结构信息完全可以直接用 SQL 按需生成自己想要的字段字典还能随时加过滤条件。下面是我常用的查询SELECT c.table_name, c.column_name, c.data_type, c.character_maximum_length AS max_len, c.is_nullable, c.column_default, coalesce(d.description, ) AS column_comment FROM information_schema.columns c LEFT JOIN pg_catalog.pg_statio_all_tables st ON st.schemaname c.table_schema AND st.relname c.table_name LEFT JOIN pg_catalog.pg_description d ON d.objoid st.relid AND d.objsubid c.ordinal_position WHERE c.table_schema public AND c.table_name LIKE account_% ORDER BY c.table_name, c.ordinal_position;这段 SQL 的逻辑是information_schema.columns 提供字段的基础元数据表名、字段名、类型、长度、是否可空、默认值pg_description 提供字段注释。两者通过表的物理对象 ID 和字段序号关联。coalesce 函数保证没有注释的字段输出为空字符串而不是 NULL方便直接导出 CSV。拿这个查询和 Navicat 导出的字典对比你会发现它有几个不可替代的优势第一永远和当前数据库结构一致第二可以按表前缀、字段名模糊过滤比如只想看 account_move 表或者只看所有含 partner 的字段第三可以随时调整输出列比如把注释换成中文术语表。如果你需要一份和原字典一样格式的文档把这个查询的结果导出为 CSV再用 pandas 处理成 Markdown 表格即可整个过程不超过两分钟。最后一个经验也是我这些年养成的习惯凡是拿到任何一份数据字典不管是中文翻译版还是原始导出版第一件事永远是连上目标数据库跑一次 information_schema 查询核对表数量和关键字段是否存在。我之前接手过一个项目对方信誓旦旦说库版本一致结果实际库里比那份字典多出两个新版本字段报表上线当天才对不上数一群人加班到凌晨排查最后原因就是字典过期。从那以后我每次做报表开发都强制走一遍这个核对流程几秒钟的查询换来的是一整天的安稳。希望这份 Odoo 17 中文数据字典和这套读字典的方法能帮你在项目里少踩几个坑也少熬几次夜。本文还有配套的精品资源点击获取