odoo-oca-developer by miquelalzanillas/odoo-oca-convention-skill
npx skills add https://github.com/miquelalzanillas/odoo-oca-convention-skill --skill odoo-oca-developer遵循 OCA 惯例和最佳实践的 Odoo 模块开发专家助手。
使用 OCA 模板创建具有适当结构和惯例的新 Odoo 模块。
快速开始:
python scripts/init_oca_module.py my_module_name --path /path/to/addons --version 17.0
此命令提供:
__manifest__.py__init__.py 导入模块命名约定:
sale_order_import(而非 sale_orders_import)base_ 前缀(例如:)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
base_location_nutsl10n_CC_ 前缀(例如:l10n_es_pos)mail_forward)crm_partner_firstname)严格遵守 OCA 惯例。详细指南请参考 oca_conventions.md。
基本结构:
module_name/
├── __init__.py
├── __manifest__.py
├── models/
│ ├── __init__.py
│ └── <model_name>.py
├── views/
│ └── <model_name>_views.xml
├── security/
│ ├── ir.model.access.csv
│ └── <model_name>_security.xml
├── data/
│ └── <model_name>_data.xml
├── readme/
│ ├── DESCRIPTION.rst
│ ├── USAGE.rst
│ └── CONTRIBUTORS.rst
└── tests/
├── __init__.py
└── test_<feature>.py
关键原则:
models/sale_order.pyviews/sale_order_views.xml_demo 后缀:demo/sale_order_demo.xmlmigrations/17.0.1.0.0/manifest.py 要点:
{
'name': 'Module Name',
'version': '17.0.1.0.0', # {odoo}.x.y.z 格式
'category': 'Sales',
'license': 'AGPL-3', # 或 LGPL-3
'author': 'Your Company, Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/<repository>',
'depends': ['base', 'sale'],
'data': [
'security/ir.model.access.csv',
'views/model_name_views.xml',
],
'installable': True,
}
Python 代码结构:
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class SaleOrder(models.Model):
_inherit = 'sale.order'
# 字段
custom_field = fields.Char(string="Custom Field")
# 计算方法
@api.depends('order_line')
def _compute_total(self):
for order in self:
order.total = sum(order.order_line.mapped('price_total'))
# 业务方法
def action_custom(self):
self.ensure_one()
# 实现
XML 命名约定:
<model_name>_view_<type>(例如:sale_order_view_form)<model_name>_action(例如:sale_order_action)<model_name>_menu<model_name>_group_<name>_demo 后缀遵循 OpenUpgrade 模式在不同 Odoo 版本之间迁移模块。完整指南请参见 openupgrade_migration.md。
迁移结构:
module_name/
└── migrations/
└── 17.0.1.0.0/
├── pre-migration.py
├── post-migration.py
└── noupdate_changes.xml
预迁移示例:
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
# 在模块加载前重命名字段
openupgrade.rename_fields(env, [
('sale.order', 'sale_order', 'old_field', 'new_field'),
])
# 重命名模型
openupgrade.rename_models(env.cr, [
('old.model', 'new.model'),
])
后迁移示例:
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
# 将旧值映射到新值
openupgrade.map_values(
env.cr,
openupgrade.get_legacy_name('state'),
'state',
[('draft', 'pending'), ('confirm', 'confirmed')],
table='sale_order',
)
# 重新计算字段
env['sale.order'].search([])._compute_total()
常见迁移任务:
openupgrade.rename_fields()openupgrade.rename_models()openupgrade.rename_tables()openupgrade.map_values()openupgrade.delete_records_safely_by_xml_id()遵循 OCA 模式扩展核心 Odoo 模块。
继承现有模型:
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
custom_field = fields.Char(string="Custom Info")
扩展现有视图:
<record id="res_partner_view_form" model="ir.ui.view">
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='email']" position="after">
<field name="custom_field"/>
</xpath>
</field>
</record>
模块依赖:
__manifest__.py 中声明依赖depends 键external_dependencies验证模块结构:
python scripts/validate_module.py /path/to/module
检查内容:
__init__.py、__manifest__.py)代码质量工具:
# 安装用于 OCA 检查的 pre-commit
pip install pre-commit
pre-commit install
# 运行检查
pre-commit run --all-files
# 运行特定检查
flake8 module_name/
pylint --load-plugins=pylint_odoo module_name/
"我需要创建一个新的 Odoo 模块" → 使用 scripts/init_oca_module.py 生成 OCA 兼容结构 → 使用模块详情编辑 __manifest__.py → 在 models/ 目录中创建模型 → 在 views/ 目录中创建视图 → 在 security/ 中添加安全规则 → 更新 readme/ 文档 → 运行验证:scripts/validate_module.py
"我需要将模块迁移到新的 Odoo 版本" → 检查 OpenUpgrade 以了解破坏性变更 → 创建迁移文件夹:migrations/<new_version>/ → 为模式变更编写预迁移脚本 → 为数据转换编写后迁移脚本 → 在数据库副本上测试 → 参考 openupgrade_migration.md
"我需要扩展一个核心 Odoo 模块" → 创建一个新模块,并在 depends 中包含核心模块 → 使用 _inherit 扩展模型 → 使用 inherit_id 扩展视图 → 遵循 OCA 命名:<core_module>_<feature> → 保持变更最小化且聚焦
"我不确定我的模块是否遵循 OCA 惯例" → 运行 scripts/validate_module.py → 检查 oca_conventions.md → 检查 manifest.py 中的必需键 → 验证文件命名和结构 → 确保 OCA 作者归属
scripts/init_oca_module.py_logger.debug()格式:[标签] 模块名: 简短摘要
常用标签:
[ADD] - 新功能/模块[FIX] - 错误修复[REF] - 重构[IMP] - 改进[MIG] - 迁移[REM] - 移除total = fields.Float(compute='_compute_total', store=True)
@api.depends('line_ids.amount')
def _compute_total(self):
for record in self:
record.total = sum(record.line_ids.mapped('amount'))
<xpath expr="//field[@name='partner_id']" position="after">
<field name="custom_field"/>
</xpath>
<record id="group_custom" model="res.groups">
<field name="name">Custom Access</field>
<field name="category_id" ref="base.module_category_sales"/>
</record>
openupgrade.map_values(
env.cr,
openupgrade.get_legacy_name('old_field'),
'new_field',
[('old_value', 'new_value')],
table='model_table',
)
模块未出现在应用中
'installable': Trueodoo-bin -u module_name -d database导入错误
迁移失败
\d table 验证表/列名openupgrade.logged_query() 进行调试测试失败
tagged('post_install', '-at_install')@users() 以最小用户权限进行测试freezegun创建模块:
python scripts/init_oca_module.py my_module --version 17.0
验证模块:
python scripts/validate_module.py path/to/module
检查惯例: 参见 oca_conventions.md
迁移指南: 参见 openupgrade_migration.md
模块模板: 从 assets/module_template/ 复制
每周安装次数
110
仓库
GitHub 星标数
2
首次出现
2026年2月5日
安全审计
安装于
opencode106
gemini-cli104
github-copilot103
codex102
amp94
kimi-cli94
Expert assistant for Odoo module development following OCA conventions and best practices.
Create new Odoo modules from OCA template with proper structure and conventions.
Quick Start:
python scripts/init_oca_module.py my_module_name --path /path/to/addons --version 17.0
What this provides:
__manifest__.py with required keys__init__.py importsModule naming conventions:
sale_order_import (not sale_orders_import)base_ (e.g., base_location_nuts)l10n_CC_ (e.g., l10n_es_pos)mail_forward)crm_partner_firstname)Follow OCA conventions strictly. Reference oca_conventions.md for detailed guidelines.
Essential structure:
module_name/
├── __init__.py
├── __manifest__.py
├── models/
│ ├── __init__.py
│ └── <model_name>.py
├── views/
│ └── <model_name>_views.xml
├── security/
│ ├── ir.model.access.csv
│ └── <model_name>_security.xml
├── data/
│ └── <model_name>_data.xml
├── readme/
│ ├── DESCRIPTION.rst
│ ├── USAGE.rst
│ └── CONTRIBUTORS.rst
└── tests/
├── __init__.py
└── test_<feature>.py
Key principles:
models/sale_order.pyviews/sale_order_views.xml_demo suffix: demo/sale_order_demo.xmlmigrations/17.0.1.0.0/manifest.py essentials:
{
'name': 'Module Name',
'version': '17.0.1.0.0', # {odoo}.x.y.z format
'category': 'Sales',
'license': 'AGPL-3', # or LGPL-3
'author': 'Your Company, Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/<repository>',
'depends': ['base', 'sale'],
'data': [
'security/ir.model.access.csv',
'views/model_name_views.xml',
],
'installable': True,
}
Python code structure:
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class SaleOrder(models.Model):
_inherit = 'sale.order'
# Fields
custom_field = fields.Char(string="Custom Field")
# Compute methods
@api.depends('order_line')
def _compute_total(self):
for order in self:
order.total = sum(order.order_line.mapped('price_total'))
# Business methods
def action_custom(self):
self.ensure_one()
# Implementation
XML naming conventions:
<model_name>_view_<type> (e.g., sale_order_view_form)<model_name>_action (e.g., sale_order_action)<model_name>_menu<model_name>_group_<name>_demoMigrate modules between Odoo versions following OpenUpgrade patterns. See openupgrade_migration.md for complete guide.
Migration structure:
module_name/
└── migrations/
└── 17.0.1.0.0/
├── pre-migration.py
├── post-migration.py
└── noupdate_changes.xml
Pre-migration example:
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
# Rename fields before module loads
openupgrade.rename_fields(env, [
('sale.order', 'sale_order', 'old_field', 'new_field'),
])
# Rename models
openupgrade.rename_models(env.cr, [
('old.model', 'new.model'),
])
Post-migration example:
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
# Map old values to new
openupgrade.map_values(
env.cr,
openupgrade.get_legacy_name('state'),
'state',
[('draft', 'pending'), ('confirm', 'confirmed')],
table='sale_order',
)
# Recompute fields
env['sale.order'].search([])._compute_total()
Common migration tasks:
openupgrade.rename_fields()openupgrade.rename_models()openupgrade.rename_tables()openupgrade.map_values()openupgrade.delete_records_safely_by_xml_id()Extend core Odoo modules following OCA patterns.
Inherit existing model:
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
custom_field = fields.Char(string="Custom Info")
Extend existing view:
<record id="res_partner_view_form" model="ir.ui.view">
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='email']" position="after">
<field name="custom_field"/>
</xpath>
</field>
</record>
Module dependencies:
__manifest__.pydepends key for Odoo core/OCA modulesexternal_dependencies for Python packagesValidate module structure:
python scripts/validate_module.py /path/to/module
What is checked:
__init__.py, __manifest__.py)Code quality tools:
# Install pre-commit for OCA checks
pip install pre-commit
pre-commit install
# Run checks
pre-commit run --all-files
# Run specific checks
flake8 module_name/
pylint --load-plugins=pylint_odoo module_name/
"I need to create a new Odoo module" → Use scripts/init_oca_module.py to generate OCA-compliant structure → Edit __manifest__.py with module details → Create models in models/ directory → Create views in views/ directory → Add security rules in security/ → Update readme/ documentation → Run validation: scripts/validate_module.py
"I need to migrate a module to a new Odoo version" → Check OpenUpgrade for breaking changes → Create migration folder: migrations/<new_version>/ → Write pre-migration script for schema changes → Write post-migration script for data transformation → Test on copy of production database → Reference openupgrade_migration.md
"I need to extend a core Odoo module" → Create new module with core module in depends → Use _inherit to extend models → Use inherit_id to extend views → Follow OCA naming: <core_module>_<feature> → Keep changes minimal and focused
"I'm not sure if my module follows OCA conventions" → Run scripts/validate_module.py → Check oca_conventions.md → Review manifest.py for required keys → Verify file naming and structure → Ensure OCA author attribution
scripts/init_oca_module.py_logger.debug() for import errorsFormat: [TAG] module_name: short summary
Common tags:
[ADD] - New feature/module[FIX] - Bug fix[REF] - Refactoring[IMP] - Improvement[MIG] - Migration[REM] - Removaltotal = fields.Float(compute='_compute_total', store=True)
@api.depends('line_ids.amount')
def _compute_total(self):
for record in self:
record.total = sum(record.line_ids.mapped('amount'))
<xpath expr="//field[@name='partner_id']" position="after">
<field name="custom_field"/>
</xpath>
<record id="group_custom" model="res.groups">
<field name="name">Custom Access</field>
<field name="category_id" ref="base.module_category_sales"/>
</record>
openupgrade.map_values(
env.cr,
openupgrade.get_legacy_name('old_field'),
'new_field',
[('old_value', 'new_value')],
table='model_table',
)
Module not appearing in Apps
'installable': True in manifest.pyodoo-bin -u module_name -d databaseImport errors
Migration fails
\d table in psqlopenupgrade.logged_query() for debuggingTests failing
tagged('post_install', '-at_install')@users()freezegunCreate module:
python scripts/init_oca_module.py my_module --version 17.0
Validate module:
python scripts/validate_module.py path/to/module
Check conventions: See oca_conventions.md
Migration guide: See openupgrade_migration.md
Module template: Copy from assets/module_template/
Weekly Installs
110
Repository
GitHub Stars
2
First Seen
Feb 5, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykPass
Installed on
opencode106
gemini-cli104
github-copilot103
codex102
amp94
kimi-cli94
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
120,000 周安装