第一章:Odoo开发环境搭建
说实话,很多初学者在Odoo开发上栽跟头,不是代码写不对,而是环境没搭好。我见过太多人花了两天时间装环境,最后心态崩了。今天咱们就把这事一次性搞定。
1.1 从源码安装Odoo
我个人习惯用源码安装,为什么?因为调试方便,你能看到每一行代码的执行过程。用deb包或者Docker虽然省事,但出了问题你根本不知道去哪找原因。
核心思路:从GitHub拉取Odoo源码,用Python虚拟环境运行。这样你的开发环境是隔离的,不会污染系统Python。
先装依赖。Ubuntu系统下,执行:
sudo apt update
sudo apt install git python3-pip python3-dev libxml2-dev libxslt1-dev \
libldap2-dev libsasl2-dev libssl-dev libjpeg-dev zlib1g-dev \
libpq-dev libffi-dev libfreetype6-dev liblcms2-dev libopenjp2-7-dev \
libtiff5-dev libwebp-dev libharfbuzz-dev libfribidi-dev
嗯,这里要注意,不同Ubuntu版本包名可能略有差异。我曾在Ubuntu 20.04上踩过坑,少装了一个libopenjp2-7-dev,结果图片处理模块死活编译不过。
然后拉取源码:
git clone https://github.com/odoo/odoo.git --depth 1 --branch 17.0
cd odoo
为什么加--depth 1?因为只取最新版本,省时间省空间。你想想看,整个Odoo仓库历史有好几百MB,我们开发用不着那些。
创建虚拟环境:
python3 -m venv odoo-venv
source odoo-venv/bin/activate
pip install -r requirements.txt
这里有个坑——requirements.txt里有些包在国内下载很慢。我建议你换国内镜像源:
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
1.2 配置PostgreSQL数据库
Odoo离不开PostgreSQL,这是它的数据大本营。安装很简单:
sudo apt install postgresql postgresql-client
sudo systemctl start postgresql
然后创建一个数据库用户,名字要和你的Linux用户名一致,否则Odoo连不上。为什么?因为Odoo默认用peer认证,它会拿当前系统用户名去连数据库。
sudo su - postgres
createuser -s $(whoami)
exit
验证一下:
psql -d postgres -c "SELECT version();"
看到版本号就说明搞定了。我曾经帮一个同事排查问题,他折腾了半天连不上数据库,最后发现是用户名大小写没对上。这种小问题最磨人。
1.3 使用PyCharm调试Odoo
说实话,没有调试器的开发就像蒙着眼睛走路。PyCharm是我最顺手的工具,没有之一。
配置步骤:
- 用PyCharm打开Odoo源码目录
- 设置Python解释器为刚才创建的虚拟环境
- 添加一个Run Configuration:
Script path: /path/to/odoo/odoo-bin
Parameters: --addons-path=addons --db-filter=my_db
Working directory: /path/to/odoo
Environment variables: PYTHONUNBUFFERED=1
小技巧:加上--db-filter=my_db可以过滤数据库,避免启动时加载一堆不相干的库。我每次新建项目都会设这个参数,启动速度快不少。
然后你就可以在代码里打断点了。比如在odoo/http.py的dispatch方法里打个断点,看看请求是怎么被路由的。这种体验,用命令行是感受不到的。
1.4 理解Odoo模块结构
Odoo的模块结构其实很规整。你随便打开一个模块,目录结构都差不多:
my_module/
├── __init__.py
├── __manifest__.py
├── models/
│ ├── __init__.py
│ └── my_model.py
├── views/
│ └── my_view.xml
├── security/
│ └── ir.model.access.csv
├── data/
│ └── demo_data.xml
├── static/
│ └── description/
│ └── icon.png
└── tests/
└── __init__.py
我来解释一下每个文件的作用:
| 文件/目录 | 作用 |
|---|---|
__manifest__.py |
模块的身份证,包含名称、版本、依赖、数据文件列表等 |
models/ |
业务逻辑层,定义数据模型和业务方法 |
views/ |
界面层,定义表单、列表、搜索视图 |
security/ |
权限控制,定义访问规则和用户组 |
data/ |
预置数据,比如演示数据、默认配置 |
static/ |
静态资源,图片、CSS、JS文件 |
tests/ |
单元测试,保证代码质量 |
这里有个关键点——__manifest__.py里的depends字段。它声明了模块依赖哪些其他模块。我见过有人写模块不声明依赖,结果运行时各种报错。说白了,Odoo的模块加载顺序就是靠这个字段决定的。
避坑指南:我曾经接手过一个项目,模块里依赖了sale但没写进depends。结果升级模块时,sale的视图先加载,而依赖模块的字段还没创建,直接报字段不存在。这种问题排查起来特别费劲。
再看models/my_model.py的典型写法:
from odoo import models, fields, api
class MyModel(models.Model):
_name = 'my.model'
_description = '我的模型'
_inherit = 'mail.thread' # 继承消息模块
name = fields.Char(string='名称', required=True)
active = fields.Boolean(string='启用', default=True)
description = fields.Text(string='描述')
@api.depends('name')
def _compute_display_name(self):
for record in self:
record.display_name = f"[{record.id}] {record.name}"
注意_name的命名规则——用点号分隔,比如my.model。Odoo内部会把它转成数据库表名my_model。这个命名要全局唯一,不能跟其他模块冲突。
嗯,到这里环境搭建和模块结构就讲完了。你可能会问:「这些我都会了,下一步学什么?」别急,下一章咱们就动手写一个真正的业务模块,从0到1走一遍。