1. 环境准备与基础配置在开始构建Odoo12业务模块之前我们需要先搭建好开发环境。这个过程就像盖房子前要打好地基虽然看起来繁琐但每一步都至关重要。首先需要安装Python 3.5以上版本这是Odoo12运行的基础环境。建议直接到Python官网下载最新稳定版安装时记得勾选Add Python to PATH选项这样后续操作会方便很多。我刚开始学习时没注意这个选项结果每次运行Python都要输入完整路径走了不少弯路。开发工具推荐使用PyCharm专业版它对数据库操作的支持比社区版更完善。安装完成后我们需要配置PostgreSQL数据库这是Odoo的默认数据库系统。安装PostgreSQL时建议设置一个简单好记的密码因为后续开发中会频繁用到。接下来获取Odoo12源代码。官网提供了社区版和企业版我们选择社区版即可。下载后建议将解压后的文件夹重命名为简单的名称比如odoo12-source这样后续路径配置会更清晰。虚拟环境的配置是很多新手容易忽略的步骤。通过virtualenv创建独立的Python环境可以避免不同项目间的依赖冲突。我习惯用以下命令创建虚拟环境virtualenv odoo12-env source odoo12-env/bin/activate # Linux/Mac odoo12-env\Scripts\activate # Windows安装完虚拟环境后我们需要安装Odoo的依赖包。这些依赖都列在源码目录下的requirements.txt文件中。为了提高安装速度可以使用国内镜像源pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple2. 项目结构与配置文件搭建好基础环境后我们需要规划项目目录结构。一个典型的Odoo项目目录应该包含以下内容/odoo12-source (Odoo源码)/addons (存放自定义模块)/config (配置文件)/odoo-data (会话和附件存储)在项目根目录下创建run.py文件作为启动入口内容如下import os import sys sys.path.append(/path/to/odoo12-source) # 替换为你的源码路径 import odoo if __name__ __main__: odoo.cli.main()配置文件(odoo.conf)是Odoo运行的核心需要特别注意以下几个关键参数[options] addons_path /path/to/odoo12-source/addons,/path/to/your/addons admin_passwd 123456 # 管理密码 data_dir /path/to/odoo-data db_host localhost db_port 5432 db_user odoo db_password odoo我曾经因为addons_path配置错误导致模块无法识别花了半天时间排查。建议在配置完成后先用命令行测试是否能正常启动python run.py -c /path/to/odoo.conf3. 创建第一个业务模块现在我们可以开始创建第一个业务模块了。Odoo提供了scaffold命令来生成模块骨架python run.py scaffold my_first_module /path/to/addons这个命令会在addons目录下生成一个包含基础结构的模块文件夹。最重要的两个文件是manifest.py: 模块的元数据描述文件models/: 存放数据模型的目录manifest.py文件定义了模块的基本信息我建议至少包含以下内容{ name: 我的第一个模块, summary: 学习Odoo开发的入门模块, description: 这是一个用于学习Odoo开发的示例模块, author: 你的名字, version: 0.1, depends: [base], data: [ views/views.xml, security/ir.model.access.csv, ], }在models目录下我们可以创建业务模型。假设我们要开发一个简单的图书管理系统可以创建book.pyfrom odoo import models, fields class Book(models.Model): _name library.book _description 图书信息 name fields.Char(string书名, requiredTrue) author fields.Char(string作者) publish_date fields.Date(string出版日期) price fields.Float(string价格) is_available fields.Boolean(string是否可借, defaultTrue)记得在models/init.py中导入这个模型文件from . import book4. 设计数据模型与字段Odoo的模型系统是其最强大的功能之一。在前面的图书模型中我们已经定义了几个基本字段。现在让我们深入探讨模型设计的细节。字段类型的选择很重要常见的有Char: 短文本如书名、作者名Text: 长文本如书籍简介Integer: 整数如库存数量Float: 浮点数如价格Boolean: 布尔值如是否可借Date/Datetime: 日期和时间Binary: 二进制数据如图书封面图片对于图书管理系统我们可能需要添加更多字段class Book(models.Model): # ... 前面已有的字段 category_id fields.Many2one(library.category, string分类) publisher_id fields.Many2one(library.publisher, string出版社) borrower_ids fields.Many2many(res.partner, string借阅人) edition fields.Integer(string版次) isbn fields.Char(stringISBN) description fields.Text(string内容简介) cover_image fields.Binary(string封面图片)模型间的关系是业务系统的核心。Odoo提供了三种关系字段Many2one: 多对一关系如多本书属于一个分类One2many: 一对多关系如一个出版社出版多本书Many2many: 多对多关系如多个人可以借阅多本书我们可以为分类和出版社创建单独的模型class Category(models.Model): _name library.category _description 图书分类 name fields.Char(string分类名称, requiredTrue) book_ids fields.One2many(library.book, category_id, string书籍) class Publisher(models.Model): _name library.publisher _description 出版社 name fields.Char(string出版社名称, requiredTrue) address fields.Text(string地址) book_ids fields.One2many(library.book, publisher_id, string出版书籍)5. 视图设计与实现模型定义好后我们需要创建视图让用户能够操作这些数据。Odoo的视图系统基于XML定义主要包括以下几种类型菜单(menu): 定义导航结构列表(tree)视图: 显示记录列表表单(form)视图: 显示和编辑单条记录动作(action): 定义视图如何被打开首先在views目录下创建book_views.xml文件odoo !-- 列表视图 -- record idview_book_tree modelir.ui.view field namename图书列表/field field namemodellibrary.book/field field namearch typexml tree field namename/ field nameauthor/ field namecategory_id/ field nameis_available/ /tree /field /record !-- 表单视图 -- record idview_book_form modelir.ui.view field namename图书表单/field field namemodellibrary.book/field field namearch typexml form sheet group field namename/ field nameauthor/ field nameisbn/ field namecategory_id/ field namepublisher_id/ /group group field namepublish_date/ field nameprice/ field nameedition/ field nameis_available/ /group group field namedescription/ /group /sheet /form /field /record !-- 窗口动作 -- record idaction_book modelir.actions.act_window field namename图书管理/field field nameres_modellibrary.book/field field nameview_modetree,form/field /record !-- 菜单项 -- menuitem idmenu_library_root name图书管理系统/ menuitem idmenu_library_book name图书管理 parentmenu_library_root actionaction_book/ /odoo视图设计有几个实用技巧使用标签组织字段使表单更整洁列表视图中只显示关键字段避免信息过载表单视图可以分多个区块按功能划分合理设置字段的readonly、required等属性6. 权限控制与模块安装在Odoo中权限控制是通过安全规则实现的。我们需要在security目录下创建ir.model.access.csv文件定义不同用户组的访问权限id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_library_book,library.book,model_library_book,base.group_user,1,1,1,0 access_library_category,library.category,model_library_category,base.group_user,1,0,0,0 access_library_publisher,library.publisher,model_library_publisher,base.group_user,1,1,1,1这个CSV文件定义了普通用户(base.group_user)对图书有读写创建权限但不能删除对分类只有读权限对出版社有完全权限记得在__manifest__.py中添加这个安全文件data: [ security/ir.model.access.csv, views/book_views.xml, ],现在可以安装模块了。启动Odoo服务后登录后台(默认账号admin/admin)进入应用菜单点击更新应用列表搜索你的模块名称点击安装安装成功后你应该能在主菜单看到图书管理系统的入口。如果看不到请检查是否在__manifest__.py中正确引用了视图文件菜单项是否关联了正确的action权限设置是否正确7. 进阶功能与最佳实践基础模块运行后我们可以添加更多实用功能。比如为图书添加状态字段和相应的业务逻辑class Book(models.Model): # ... 已有字段 state fields.Selection([ (available, 可借阅), (borrowed, 已借出), (lost, 遗失)], string状态, defaultavailable) def action_borrow(self): self.write({state: borrowed}) def action_return(self): self.write({state: available}) def action_lost(self): self.write({state: lost})然后在表单视图中添加状态栏和按钮form header field namestate widgetstatusbar/ button nameaction_borrow string借出 typeobject classoe_highlight/ button nameaction_return string归还 typeobject/ button nameaction_lost string标记遗失 typeobject/ /header !-- 原有表单内容 -- /form开发Odoo模块时有几个最佳实践值得注意命名规范模型名使用点号分隔的小写字母如library.book模块化设计将相关模型放在一起如图书、分类、出版社视图组织按功能拆分视图文件如book_views.xml, category_views.xml权限最小化只授予必要的权限多语言支持使用_()函数包裹所有显示文本调试是开发中不可避免的。Odoo提供了几种调试方法在启动命令中添加--devall开启开发者模式使用pdb设置断点import pdb; pdb.set_trace()查看服务端日志获取错误信息8. 测试与部署完成开发后我们需要对模块进行测试。Odoo支持自动化测试可以在模块中创建tests目录from odoo.tests.common import TransactionCase class TestBook(TransactionCase): def setUp(self): super(TestBook, self).setUp() self.Book self.env[library.book] def test_book_creation(self): 测试图书创建 book self.Book.create({ name: 测试图书, author: 测试作者 }) self.assertEqual(book.is_available, True)要运行测试使用以下命令python run.py -c odoo.conf -i your_module -d your_db --test-enable部署模块时建议打包模块为zip文件在生产环境的addons目录中解压更新应用列表并安装/升级模块检查日志确认没有错误对于大型项目可以考虑使用版本控制(Git)管理代码设置持续集成(CI)流程编写详细的文档创建数据迁移脚本开发过程中常见的坑包括忘记在__init__.py中导入模型文件视图文件中XML语法错误权限配置不足导致功能不可见字段名拼写错误忘记在__manifest__.py中声明数据文件记住Odoo模块开发是一个迭代过程。从简单功能开始逐步添加复杂特性定期测试这样能避免很多问题。