odoo19-syntax
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOdoo 19 Syntax Skill
Odoo 19语法技能
This skill ensures generated code matches Odoo 19 (released September 2025) syntax conventions, NOT older versions. Odoo 19 introduces ~130 model renames, the largest schema change since Odoo 14, plus continued enforcement of changes from Odoo 17/18.
本技能确保生成的代码符合Odoo 19(2025年9月发布)的语法规范,而非旧版本。Odoo 19引入了约130个模型重命名,这是自Odoo 14以来最大的架构变更,同时持续推行Odoo 17/18中的变更。
CRITICAL: Detect the version FIRST
关键:先检测版本
This skill applies ONLY to Odoo 19 projects. Before suggesting any syntax, determine the project's Odoo version. If the project is NOT Odoo 19, stop using this skill and let the user know — do not silently apply Odoo 19 syntax to an Odoo 17/18 codebase, because it will break.
Detection priority (try in order, stop at the first that works):
本技能仅适用于Odoo 19项目。 在建议任何语法之前,请确定项目的Odoo版本。如果项目不是Odoo 19,请停止使用本技能并告知用户——不要将Odoo 19语法静默应用到Odoo 17/18代码库中,否则会导致代码崩溃。
检测优先级(按顺序尝试,找到有效结果后停止):
1. Read __manifest__.py
of the target module
__manifest__.py1. 读取目标模块的__manifest__.py
__manifest__.pyLook for the field. The first two numbers indicate the Odoo version:
versionpython
{
'name': 'My Module',
'version': '19.0.1.0.0', # ← Odoo 19
# ...
}- → Odoo 19, this skill applies.
'19.0.x.x.x' - ,
'18.0.x.x.x', etc. → Different version, STOP and skip this skill.'17.0.x.x.x' - Missing version field → Continue to step 2.
If multiple files exist, read the one for the module being edited. If unsure which module, check the file path of the user's request (e.g., → read ).
__manifest__.pyaddons/sale_custom/models/...addons/sale_custom/__manifest__.py查找字段。前两位数字表示Odoo版本:
versionpython
{
'name': 'My Module',
'version': '19.0.1.0.0', # ← Odoo 19
# ...
}- → Odoo 19,适用本技能。
'19.0.x.x.x' - 、
'18.0.x.x.x'等 → 其他版本,停止并跳过本技能。'17.0.x.x.x' - 缺少version字段 → 继续步骤2。
如果存在多个文件,请读取正在编辑的模块对应的文件。如果不确定是哪个模块,请检查用户请求的文件路径(例如: → 读取)。
__manifest__.pyaddons/sale_custom/models/...addons/sale_custom/__manifest__.py2. Read Odoo source release.py
release.py2. 读取Odoo源码的release.py
release.pyIf the project is a full Odoo source checkout, look for or containing :
odoo/release.pyodoo/__init__.pyversion_infopython
version_info = (19, 0, 0, 'final', 0, '')The first integer is the major version.
Common locations to check (use or ):
viewbashfind./odoo/release.py./release.py- followed by source tree
./odoo-bin
如果项目是完整的Odoo源码检出版本,请查找包含的或:
version_infoodoo/release.pyodoo/__init__.pypython
version_info = (19, 0, 0, 'final', 0, '')第一个整数是主版本号。
常见检查位置(使用或bash的命令):
viewfind./odoo/release.py./release.py- 及后续源码树
./odoo-bin
3. Check requirements.txt
, pyproject.toml
, or Docker config
requirements.txtpyproject.toml3. 检查requirements.txt
、pyproject.toml
或Docker配置
requirements.txtpyproject.tomlSometimes the version is pinned via:
- A line like in
odoo==19.0.*requirements.txt - An image like in
odoo:19.0ordocker-compose.ymlDockerfile
有时版本会通过以下方式固定:
- 中的
requirements.txt行odoo==19.0.* - 或
docker-compose.yml中的Dockerfile镜像odoo:19.0
4. Ask the user
4. 询问用户
If steps 1–3 fail, ask the user directly: "I couldn't auto-detect the Odoo version from the project files. Which version is this — Odoo 19, or something else?" Do not assume Odoo 19 by default.
如果步骤1-3失败,请直接询问用户:“我无法从项目文件中自动检测Odoo版本。这是哪个版本——Odoo 19还是其他版本?”不要默认假设是Odoo 19。
Behavior when version ≠ 19
版本≠19时的处理
If detection shows the project is Odoo 17, 18, or earlier:
- Tell the user: "This project appears to be on Odoo X.0, not Odoo 19. I'll skip the Odoo 19 syntax skill and write code matching Odoo X.0 conventions instead."
- Do NOT load the references in this skill for code generation.
- Use your general Odoo knowledge for that version.
If the project is Odoo 19 (or version is uncertain and the user confirmed 19), proceed with the rest of this skill.
如果检测到项目是Odoo 17、18或更早版本:
- 告知用户:“该项目似乎使用的是Odoo X.0版本,而非Odoo 19。我将跳过Odoo 19语法技能,编写符合Odoo X.0规范的代码。”
- 代码生成时不要加载本技能中的参考内容。
- 使用你对该版本Odoo的通用知识。
如果项目是Odoo 19(或版本不确定但用户确认是19),请继续使用本技能的剩余内容。
How to use this skill (once Odoo 19 is confirmed)
如何使用本技能(确认是Odoo 19后)
The detailed syntax rules are split into reference files by domain. Load only the references relevant to the current task — you don't need all of them every time.
| Task involves... | Load this reference |
|---|---|
| Python models, ORM, fields, methods, constraints | |
| XML views (form, list/tree, kanban, search), QWeb | |
| HTTP controllers, routes, RPC endpoints | |
OWL components, services, JS in | |
| |
| SCSS files, asset registration | |
| Model name lookups (hr.contract? procurement.group?) | |
Always load and for any non-trivial Python+XML task — they're the most frequent source of mistakes.
references/orm.mdreferences/views.mdFor model name questions (e.g., "is the model still ?"), is the source of truth — Odoo 19 renamed 130 models.
hr.contractreferences/model_renames.md详细的语法规则按领域拆分到参考文件中。仅加载与当前任务相关的参考内容——不需要每次都加载所有内容。
| 任务涉及... | 加载此参考 |
|---|---|
| Python模型、ORM、字段、方法、约束 | |
| XML视图(表单、列表/tree、看板、搜索)、QWeb | |
| HTTP控制器、路由、RPC端点 | |
OWL组件、服务、 | |
| |
| SCSS文件、资源注册 | |
| 模型名称查询(hr.contract?procurement.group?) | |
对于任何非简单的Python+XML任务,请务必加载和——它们是最常见错误的来源。
references/orm.mdreferences/views.md对于模型名称问题(例如:“模型还是吗?”),是权威来源——Odoo 19重命名了130个模型。
hr.contractreferences/model_renames.mdWorkflow for a code-generation request
代码生成请求的工作流程
-
Detect version (per the section above). If not Odoo 19, exit this skill.
-
Identify the task domain(s) — Python? Views? OWL? Controllers? Multiple?
-
Load relevant references — read eachfile you need.
references/*.md -
For any model name the user mentions or you plan to use, cross-check. Do not skip this — model renames are the silent-failure category.
references/model_renames.md -
Generate code following the patterns in the references.
-
Self-check before responding: scan your draft for these red flags:Constraints, decorators, imports:
- → should be
_sql_constraints = [...]in Odoo 19_constraints = [models.Constraint(...)] - → unnecessary; use
from odoo.models import Constraintdirectlymodels.Constraint(...) - → must be
from odoo.fields import Commandfrom odoo import Command - → use
from odoo.osv.expression import OR/AND/Domain.OR(Domain.AND)from odoo import Domain - decorator → REMOVED in Odoo 19, drop it
@api.returns(...) - Helper method exposed via RPC by accident → consider
@api.private
Record/env access:- →
self._crself.env.cr - →
self._contextself.env.context - →
self._uidself.env.uid - →
self._context.get('tz')self.env.tz - →
self._context.get('allowed_company_ids')self.env.companies
Methods:- → must be
name_get(self)_compute_display_name(self) - →
read_group(...)(backend) or_read_group(...)formatted_read_group(...) - /
check_access_rights(...)→check_access_rule(...)(combined)check_access(...) - → must be
_render_qweb_pdf(...)_render(...) - import → must be
SavepointCaseTransactionCase - tuple syntax for O2M/M2M → use
(0, 0, {...})Command.create({...})
Domain syntax:- Uppercase domain operators (,
'LIKE', etc.) → must be lowercase'IN' - Complex relational subqueries via dot-notation → consider operator
('field_ids', 'any', [...])
Views (XML):- → must be inline
attrs="{...}",invisible=,readonly=required= - → must be
<tree><list> - or
<group string="..."inside<group expand="..."view → drop both, leave<search>bare<group> - → must be
t-raw="..."t-out="..." - → REMOVED in Odoo 19, must be
t-esc="..."t-out="..." - boilerplate (3 fields) → use
<chatter>shorthand<chatter/> - with nested
<t t-call>→ use attribute syntax<t t-set><t t-call="tpl" var="value"/>
Manifest, hooks, config:- signature → must be
post_init_hook(cr, registry)post_init_hook(env) - Manifest missing key → required (e.g.
'license')'LGPL-3' - in odoo.conf →
xmlrpc_porthttp_port
Controllers:- on a route called by the web client → likely should be
type="json"type="jsonrpc"
SCSS:- SCSS using for division → must use
/ormath.div(...)calc(...) - SCSS → must use
@import "..."(dart-sass)@use "..."
Renamed models (silent failures — see):model_renames.md- →
hr.contracthr.version - →
procurement.groupstock.reference - →
stock.quant.packagestock.package - →
bus.presencemail.presence - →
hr.candidatehr.applicant - → REMOVED (use
hr.employee.base)hr.employee - → REMOVED
res.partner.title - → REMOVED (data on
stock.valuation.layer)stock.move - → REMOVED
hr.expense.sheet
Renamed fields:- →
groups_id(ongroup_ids, menus, views, actions, rules)res.users - →
tax_idontax_ids;sale.order.line→taxes_idontax_idspurchase.order.line - →
product_uomon sale/purchase linesproduct_uom_id - →
purchase.order.notesnote - →
fleet.vehicle.first_contract_datecontract_date_start
Removed fields (delete from code/XML):- on
<field name="numbercall">recordsir.cron - (use
res.partner.mobile),phone,res.partner.title,res.partner.picking_warnres.partner.last_website_so_id - ,
account.move.line.product_uom_category_idproduct.uom.category_id product.template.sale_line_warn
OWL/JS specific:- →
this.pos.get_order()(camelCase)this.pos.getOrder() - →
request.website.sale_get_order()request.cart - →
request.website.pricelist_idrequest.pricelist
If any red flag fires, fix the code before showing it to the user.
-
检测版本(按照上述章节)。如果不是Odoo 19,退出本技能。
-
确定任务领域——Python?视图?OWL?控制器?多个领域?
-
加载相关参考内容——读取所需的每个文件。
references/*.md -
对于用户提及或你计划使用的任何模型名称,交叉检查。不要跳过这一步——模型重命名是会导致静默失败的类别。
references/model_renames.md -
生成代码——遵循参考内容中的模式。
-
回复前自我检查:扫描草稿中的以下危险信号:约束、装饰器、导入:
- → Odoo 19中应改为
_sql_constraints = [...]_constraints = [models.Constraint(...)] - → 不必要;直接使用
from odoo.models import Constraintmodels.Constraint(...) - → 必须改为
from odoo.fields import Commandfrom odoo import Command - → 使用
from odoo.osv.expression import OR/AND/Domain.OR(需Domain.AND)from odoo import Domain - 装饰器 → Odoo 19中已移除,请删除
@api.returns(...) - 意外通过RPC暴露的辅助方法 → 考虑使用
@api.private
记录/环境访问:- →
self._crself.env.cr - →
self._contextself.env.context - →
self._uidself.env.uid - →
self._context.get('tz')self.env.tz - →
self._context.get('allowed_company_ids')self.env.companies
方法:- → 必须改为
name_get(self)_compute_display_name(self) - →
read_group(...)(后端)或_read_group(...)formatted_read_group(...) - /
check_access_rights(...)→check_access_rule(...)(合并后的方法)check_access(...) - → 必须改为
_render_qweb_pdf(...)_render(...) - 导入 → 必须改为
SavepointCaseTransactionCase - O2M/M2M的元组语法 → 使用
(0, 0, {...})Command.create({...})
域语法:- 大写的域操作符(、
'LIKE'等) → 必须改为小写'IN' - 通过点符号实现的复杂关系子查询 → 考虑使用操作符
('field_ids', 'any', [...])
视图(XML):- → 必须改为内联的
attrs="{...}"、invisible=、readonly=required= - → 必须改为
<tree><list> - 视图中的
<search>或<group string="..."→ 删除这两个属性,保留<group expand="..."即可<group> - → 必须改为
t-raw="..."t-out="..." - → Odoo 19中已移除,必须改为
t-esc="..."t-out="..." - 模板代码(3个字段) → 使用
<chatter>简写形式<chatter/> - 嵌套的
<t t-set>→ 使用属性语法<t t-call><t t-call="tpl" var="value"/>
清单、钩子、配置:- 签名 → 必须改为
post_init_hook(cr, registry)post_init_hook(env) - 清单文件缺少键 → 必填(例如
'license')'LGPL-3' - odoo.conf中的→ 改为
xmlrpc_porthttp_port
控制器:- 被Web客户端调用的路由上的→ 应改为
type="json"type="jsonrpc"
SCSS:- 使用进行除法的SCSS → 必须使用
/或math.div(...)calc(...) - SCSS的→ 必须使用
@import "..."(dart-sass)@use "..."
重命名的模型(静默失败——见):model_renames.md- →
hr.contracthr.version - →
procurement.groupstock.reference - →
stock.quant.packagestock.package - →
bus.presencemail.presence - →
hr.candidatehr.applicant - → 已移除(使用
hr.employee.base)hr.employee - → 已移除
res.partner.title - → 已移除(数据在
stock.valuation.layer上)stock.move - → 已移除
hr.expense.sheet
重命名的字段:- →
groups_id(在group_ids、菜单、视图、动作、规则上)res.users - 上的
sale.order.line→tax_id;tax_ids上的purchase.order.line→taxes_idtax_ids - 销售/采购行上的→
product_uomproduct_uom_id - →
purchase.order.notesnote - →
fleet.vehicle.first_contract_datecontract_date_start
已移除的字段(从代码/XML中删除):- 记录上的
ir.cron<field name="numbercall"> - (使用
res.partner.mobile)、phone、res.partner.title、res.partner.picking_warnres.partner.last_website_so_id - 、
account.move.line.product_uom_category_idproduct.uom.category_id product.template.sale_line_warn
OWL/JS特定:- →
this.pos.get_order()(驼峰命名)this.pos.getOrder() - →
request.website.sale_get_order()request.cart - →
request.website.pricelist_idrequest.pricelist
如果检测到任何危险信号,请在展示给用户前修复代码。
What NOT to do
禁止事项
- Do not apply Odoo 19 conventions to projects on older versions.
- Do not skip the version-check step "because the user said Odoo 19" — verify by reading at least one project file when possible.
- Do not assume is wrong without confirming Odoo 19; it still works in 18 and earlier.
_sql_constraints - Do not tell the user "this is the Odoo way" without specifying the version — say "in Odoo 19, ..." explicitly.
- 不要将Odoo 19规范应用到旧版本项目中。
- 不要因为“用户说过是Odoo 19”就跳过版本检查步骤——尽可能通过读取至少一个项目文件进行验证。
- 不要在未确认是Odoo 19的情况下就认为是错误的;它在18及更早版本中仍然有效。
_sql_constraints - 不要不指定版本就告诉用户“这是Odoo的方式”——明确说明“在Odoo 19中,……”。