第一章: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是我最顺手的工具,没有之一。

配置步骤:

  1. 用PyCharm打开Odoo源码目录
  2. 设置Python解释器为刚才创建的虚拟环境
  3. 添加一个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.pydispatch方法里打个断点,看看请求是怎么被路由的。这种体验,用命令行是感受不到的。

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走一遍。