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.py:
from odoo import models, fields class Book(models.Model): _name = 'library.book' _description = '图书信息' name = fields.Char(string="书名", required=True) author = fields.Char(string="作者") publish_date = fields.Date(string="出版日期") price = fields.Float(string="价格") is_available = fields.Boolean(string="是否可借", default=True)记得在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(string="ISBN") 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="分类名称", required=True) book_ids = fields.One2many('library.book', 'category_id', string="书籍") class Publisher(models.Model): _name = 'library.publisher' _description = '出版社' name = fields.Char(string="出版社名称", required=True) 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 id="view_book_tree" model="ir.ui.view"> <field name="name">图书列表</field> <field name="model">library.book</field> <field name="arch" type="xml"> <tree> <field name="name"/> <field name="author"/> <field name="category_id"/> <field name="is_available"/> </tree> </field> </record> <!-- 表单视图 --> <record id="view_book_form" model="ir.ui.view"> <field name="name">图书表单</field> <field name="model">library.book</field> <field name="arch" type="xml"> <form> <sheet> <group> <field name="name"/> <field name="author"/> <field name="isbn"/> <field name="category_id"/> <field name="publisher_id"/> </group> <group> <field name="publish_date"/> <field name="price"/> <field name="edition"/> <field name="is_available"/> </group> <group> <field name="description"/> </group> </sheet> </form> </field> </record> <!-- 窗口动作 --> <record id="action_book" model="ir.actions.act_window"> <field name="name">图书管理</field> <field name="res_model">library.book</field> <field name="view_mode">tree,form</field> </record> <!-- 菜单项 --> <menuitem id="menu_library_root" name="图书管理系统"/> <menuitem id="menu_library_book" name="图书管理" parent="menu_library_root" action="action_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="状态", default="available") 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 name="state" widget="statusbar"/> <button name="action_borrow" string="借出" type="object" class="oe_highlight"/> <button name="action_return" string="归还" type="object"/> <button name="action_lost" string="标记遗失" type="object"/> </header> <!-- 原有表单内容 --> </form>开发Odoo模块时,有几个最佳实践值得注意:
- 命名规范:模型名使用点号分隔的小写字母,如library.book
- 模块化设计:将相关模型放在一起,如图书、分类、出版社
- 视图组织:按功能拆分视图文件,如book_views.xml, category_views.xml
- 权限最小化:只授予必要的权限
- 多语言支持:使用_()函数包裹所有显示文本
调试是开发中不可避免的。Odoo提供了几种调试方法:
- 在启动命令中添加--dev=all开启开发者模式
- 使用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模块开发是一个迭代过程。从简单功能开始,逐步添加复杂特性,定期测试,这样能避免很多问题。