在第一章 安装Odoo开发环境中,我们介绍了如何使用源代码附带的标准内核插件来配置Odoo实例。作为自定义Odoo默认功能的标准实践,我们创建一个单独的模块并将其保存在不同的仓库中,以便以后可以清晰地升级Odoo自有和您的自定义仓库。本章重点介绍如何向Odoo实例添加非内核或自定义插件。在Odoo中,可以从多个目录加载插件。此外,建议从单独的文件夹加载第三方插件或您自己的自定义插件,以免与Odoo核心模块产生冲突。甚至Odoo企业版也是一种插件目录,需要像加载普通插件目录一样加载它。
本章中我们将介绍以下内容:
- 配置插件路径
- 标准化实例目录布局
- 安装和升级本地插件模块
- 从GitHub安装插件模块
- 应用对插件的更改
- 应用和测试拉取请求(PR)
术语说明
在本书中,我们将交替使用插件、模块、应用和插件模块这些术语。它们都指可以从用户界面安装到Odoo中的Odoo应用程序或扩展应用程序。
配置插件路径
借助addons_path参数,可以将自己的插件模块加载到Odoo中。Odoo初始化新数据库时,它会在addons_path配置参数提供的目录中搜索插件模块。Odoo在这些目录中搜索潜在的插件模块。
addons_path中的目录应该包含子目录,每个子目录都是一个插件模块。初始化数据库后,即可安装这些目录中提供的模块。
准备工作
假设读者已经准备好了一个实例,并生成了配置文件,参见第一章将实例配置存储在文件一节。注意,Odoo的源代码位于~/odoo-dev/odoo,配置文件位于~/odoo-dev/odoo/myodoo.cfg。
如何操作
将~/odoo-dev/local-addons目录添加到实例的addons_path参数,请执行以下步骤:
- 1编辑实例的配置文件,即~/odoo-dev/myodoo.cfg。
- 找到以addons_path=开头的行。默认情况下,如下所示:
1addons_path = ~/odoo-dev/odoo/odoo/addons,~/odoo-dev/odoo/addons - 修改该行,在其后添加一个逗号,然后添加要加入至addons_path的目录名,如下所示:
1addons_path = ~odoo-dev/odoo/odoo/addons,~odoo-dev/odoo/addons,~/odoo-dev/local-addons - 在终端重新启动实例:
1$ ~/odoo-dev/odoo/odoo-bin -c myodoo.cfg
工作原理
Odoo重新启动时,会读取配置文件。addons_path变量的值应是一个以逗号分隔的目录列表。可接受相对路径,但它们是相对于当前工作目录的,因此应避免在配置文件中使用。
此时,我们仅在Odoo中配置了插件目录,但~/odoo-dev/local-addons中没有插件模块。即使向该目录添加了新插件模块,Odoo也不会在用户界面中显示此模块。为此,需要执行额外的操作,参见上一章更新插件模块列表一节。
注:背后的原因是在初始化新数据库时,Odoo会在可用模块中列举自定义模块,但若是在数据库初始化之后添加新模块,需要手动更新可用模块列表,可参见第一章 安装Odoo开发环境的更新插件模块列表一节。
更多……
第一次调用odoo-bin脚本初始化新数据库时,可以使用--addons-path
命令行参数传递一个以逗号分隔的目录列表。这将使用提供的插件路径中的所有插件初始化可用插件模块的列表。这么做时,必须显式包含基本插件目录(odoo/odoo/addons)以及核心插件目录(odoo/addons)。与前一节相比,唯一的不同是本地插件目录不能为空;必须包含至少一个子目录,该子目录具有插件模块的最小化结构。
在第三章 创建Odoo插件模块中,我们将介绍如何编写自己的模块。同时,以下是生成满足Odoo需求的快速技巧:
1 2 3 4 |
$ mkdir -p ~/odoo-dev/local-addons/dummy $ touch ~/odoo-dev/local-addons/dummy/__init__.py $ echo '{"name": "dummy", "installable": False}' > \ ~/odoo-dev/local-addons/dummy/__manifest__.py |
可以使用--save
选项将路径保存到配置文件:
1 2 3 |
$ odoo/odoo-bin -d odoo-test \ --addons-path="odoo/odoo/addons,odoo/addons,~/odoo-dev/local-addons" \ --save -c ~/odoo-dev/myodoo.cfg --stop-after-init |
本例中可使用相对路径,因为在配置文件中会转换为绝对路径。
注:由于Odoo是在从命令行配置插件路径时检查路径中的目录是否存在插件,而不是在从配置文件加载路径时做检查,因此不再需要虚拟模块。因此,可将其删除(或者在确定不需要创建新的配置文件前保留它)。
标准化实例目录布局
推荐对开发和生产环境都使用类似的目录布局。这种标准化利于执行维护操作,并且还会简化日常工作。
本节创建了一个目录结构,将具有相似生命周期或相似用途的文件分组在标准化的子目录中。
注:本节仅对希望对开发和生产环境使用相似的文件夹结构时有用。如尚不需要,可跳过此节。
此外,并非强制要求遵循此节中的文件夹结构。可根据需要修改此结构。
我们生成了一个清晰的目录结构,具有明确标记签的目录和专用角色。使用不同的目录来存储以下内容:
- 由他人维护的代码(在src/中)
- 本地特定代码
- 实例的文件存储
如何操作
创建推荐的实例布局,请执行以下步骤:
- 为每个实例创建一个目录:
12$ mkdir ~/odoo-dev/projectname$ cd ~/odoo-dev/projectname - 在名为env/的子目录中创建一个Python虚拟环境对象:
1$ python3 -m venv env - 创建一些子目录,如下所示:
1$ mkdir src local bin filestore logs
子目录的功能如下:- src/:包含Odoo本身的克隆,以及各种第三方插件项目(我们已在本节的下一步中添加了Odoo源代码)
- local/:用于保存具体实例的插件
- bin/:包含各种辅助的可执行shell脚本
- filestore/:用作文件存储
- logs/(可选):用于存储服务器日志文件
- 克隆Odoo并安装依赖(有关详细信息,请参阅第一章 安装Odoo开发环境):
12$ git clone -b 17.0 --single-branch --depth 1 https://github.com/odoo/odoo.git src/odoo$ env/bin/pip3 install -r src/odoo/requirements.txt - 将以下shell脚本保存为bin/odoo:
123456#!/bin/shROOT=$(dirname $0)/..PYTHON=$ROOT/env/bin/python3ODOO=$ROOT/src/odoo/odoo-bin$PYTHON $ODOO -c $ROOT/projectname.cfg "$@"exit $? - 使脚本可执行:
1$ chmod +x bin/odoo - 创建一个空的虚拟本地模块:
123$ mkdir -p local/dummy$ touch local/dummy/__init__.py$ echo '{"name": "dummy", "installable": False}' > local/dummy/__manifest__.py - 为实例生成配置文件:
123$ bin/odoo --stop-after-init --save \--addons-path src/odoo/odoo/addons,src/odoo/addons,local \--data-dir filestore - 添加.gitignore文件,用于告诉GitHub排除给定的目录,以便Git在提交代码时忽略这些目录;例如filestore/,env/,logs/和src/:
123456789101112# dotfiles, with exceptions:.*!.gitignore# python compiled files*.py[co]# emacs backup files*~# not tracked subdirectories/env//src//filestore//logs/ - 为实例创建一个Git仓库并将新增的文件添加到Git:
123$ git init$ git add .$ git commit -m "initial version of projectname"
工作原理
通过为每个项目创建一个虚拟环境,可以确保项目的依赖不会干扰运行不同版本Odoo或使用不同第三方插件模块的其他项目的依赖。这以占用少量磁盘空间为代价,提升隔离性和系统稳定性。
类似地,通过对不同项目使用单独的Odoo和第三方插件模块的克隆,可以让每个项目独立演进,并且只在需要的实例上安装更新,从而减少回退的风险。
bin/odoo脚本允许我们运行服务而不必记住各种路径或启动虚拟环境。也为我们设置了配置文件。可以在其中添加额外的脚本完成日常工作。例如,可以添加一个脚本来检测运行实例所需的各种第三方项目。
关于配置文件,我们这里只演示了最低限度选项,但显然可以设置更多,例如数据库名称、数据库过滤器或项目监听的端口。更多信息,请参阅第一章 安装Odoo开发环境。
最后,通过在Git仓库中管理所有这些内容,可以很容易地在将配置复制到其它电脑上,并在团队中共享开发工作。
加速贴示
为了方便项目创建,可以创建一个包含空结构的模板仓库,并为每个新项目fork该仓库。这样就不必重新输入bin/odoo脚本、.gitignore文件以及其他需要的模板文件(持续集成(CI)配置、README.md、变更日志等)。
更多……
开发复杂模块需要各种配置选项,这导致每次想要尝试配置选项时都需要更新配置文件。频繁更新配置文件可能会让人头疼,为避免这种情况,一种替代方法是从命令行传递配置选项,如下所示:
- 手动启动虚拟环境:
1$ source env/bin/activate - 进入Odoo源目录:
1$ cd src/odoo - 运行服务:
1./odoo-bin --addons-path=addons,../../local -d test-16 -i account,sale,purchase --log-level=debug
在步骤3中,我们直接从命令行传递了一些配置选项。第一个是 --addons-path
,它加载Odoo的核心插件目录 addons
和自有插件目录 local
,在其中放置自己的插件模块。-d
选项使用 test-16
数据库,如果不存在则创建一个新数据库。-i
选项将安装 account
、sale
和 purchase
模块。接下来,我们传递了 log-level
选项并将日志级别增加到 debug
,以便在日志中显示更多信息。
注:通过使用命令行,可以快速更改配置选项。还可以在终端中查看实时日志。有关所有可用选项的信息,请参阅第一章 安装Odoo开发环境,或使用
--help
命令查看所有选项的列表及每个选项的描述。
安装和升级本地插件模块
Odoo的核心功能来自其插件模块。除了Odoo本身包含的大量插件外,还可从应用商店下载或自行编写插件模块。
在本节中,我们将演示如何通过Web界面和命令行安装及升级插件模块。
使用命令行进行这些操作的主要好处有可以一次处理多个插件,并在安装或更新过程中清晰查看服务器日志,这在开发模式或脚本化安装实例时非常有用。
准备工作
确保已有一个运行中的Odoo实例,数据库已初始化,并且插件路径已正确设置。在本节中,我们将安装/升级一些插件模块。
如何操作
安装或更新插件有两种方法——使用Web界面或命令行。
通过Web界面
请执行以下步骤通过Web界面在数据库中安装新插件模块:
- 使用管理员账户连接实例并打开Apps菜单:
图2.1 – Odoo应用列表 - 使用搜索框找到您要安装的插件。以下是一些完成此任务的说明:
- 激活未安装过滤器。
- 如果在寻找特定功能的插件而不是通过功能插件,请删除Apps过滤器。
- 在搜索框中输入部分模块名称,并使用模块过滤器。
- 使用列表视图可能更易于阅读。
- 点击模块名称下方的安装按钮。
注意,一些Odoo插件模块有外部Python依赖。如系统中未安装该Python依赖,Odoo将中止安装,并显示以下对话框:
图2.2 – 外部库依赖警告
要解决此问题,只需在系统上安装相关的Python依赖。
要在数据库中更新预安装的模块,执行以下步骤:- 使用管理员账户连接实例。
- 打开应用菜单。
- 点击应用:
图2.3 – Odoo应用列表 - 使用搜索框找到要安装的插件。以下是一些小贴示:
- 激活已安装过滤器。
- 如果在寻找具体功能的插件而不是通过功能的插件,请去除应用过滤器。
- 在搜索框中输入部分插件模块名称,然后按回车键,将其用作模块过滤器。例如,输入crm并按回车键搜索CRM应用。
- 使用列表视图可能更易于阅读。
- 点击卡片右上角的三个点,然后点击升级选项:
图2.4 – 升级模块的下拉链接
启用开发者模式查看模块的技术名称。如果不知道如何激活开发者模式,请参阅第1章“安装Odoo开发环境”:
图2.5 – 应用的技术名称
启用开发者模式后,会以红字显示模块的技术名称。如果使用的是Odoo社区版,会看到一些带有升级按钮的应用。这些应用是Odoo企业版应用,要安装/使用它们,需要购买许可证。
通过命令行
执行以下步骤在数据库中安装新插件:
- 找到插件的名称。即包含
__manifest__.py
文件的目录名称,不含前导路径。 - 停止实例。如在生产数据库上运行,请先备份。
- 运行以下命令:
1$ odoo/odoo-bin -c instance.cfg -d dbname -i addon1,addon2 --stop-after-init
如果在配置文件中已设置-d dbname,则可以省略。 - 重启实例。
执行以下步骤在数据库中更新已安装的插件模块:
- 找到要更新的插件模块的名称;即包含
__manifest__.py
文件的目录名称,不含前导路径。 - 停止实例。如在生产数据库上工作,请先备份。
- 运行以下命令:
1$ odoo/odoo-bin -c instance.cfg -d dbname -u addon1 --stop-after-init
如果在配置文件中已设置-d dbname,则可以省略。 - 重启实例。
工作原理
插件模块的安装和更新是两个紧密相关的过程,但它们之间存在一些重要差异,以下两小节会进行讲解。
插件安装
安装插件时,Odoo会在其可用插件列表中查找具有所提供名称的未安装插件。还会检查该插件的依赖,如果有任何依赖,将递归进行安装,然后再安装该插件。
单个模块的安装过程有如下步骤:
- 如有依赖,运行preinit插件钩子。
- 从Python源代码加载模型定义,并在必要时更新数据库结构(详细信息,请参阅第四章 应用模型)。
- 加载插件的数据文件,并在必要时更新数据库内容(详细信息,请参阅第六章 管理模块数据)。
- 如在实例中启用了演示数据,则安装插件演示数据。
- 如有任何依赖,运行插件postinit钩子。
- 验证插件的视图定义。
- 如启用了演示数据并启用了测试,则运行插件的测试(详细信息,请参阅第十八章 自动化测试用例)。
- 更新数据库中的模块状态。
- 从插件的翻译更新数据库中的翻译(详细信息,请参阅第十一章 国际化)。
注:preinit和postinit钩子在__manifest__.py
文件中使用pre_init_hook和post_init_hook定义,分别用于在安装插件模块之前和之后调用Python函数。要了解有关init钩子的更多信息,请参阅第三章 创建Odoo插件模块。
插件更新
更新插件时,Odoo会在其可用插件模块列表中查找具有给定名称的已安装插件。还会检查该插件的反向依赖(这些依赖项依赖于所更新的插件)。如果存在反向依赖,也会递归更新。
单个插件模块的更新包含以下步骤:
- 运行插件模块的预迁移步骤(如有)(详细信息,请参阅第六章 管理模块数据)。
- 从Python源代码加载模型定义,并在必要时更新数据库结构(详细信息,请参阅第四章 应用模型)。
- 加载插件的数据文件,并在必要时更新数据库内容(详细信息,请参阅第六章 管理模块数据)。
- 如在实例中启用了演示数据,则更新插件的演示数据。
- 如果模块存在迁移方法,运行插件的后迁移步骤(详细信息,请参阅第六章 管理模块数据)。
- 验证插件的视图定义。
- 如果启用了演示数据并启用了测试,则运行插件的测试(详细信息,请参阅第十八章 自动化测试用例)。
- 更新数据库中的模块状态。
- 从插件的翻译更新数据库中的翻译(详细信息,请参阅第十一章 国际化)。
注:注意,更新未安装的插件模块不会产生任何效果。但安装已安装的插件模块会重新安装该插件,这可能对某些包含数据的文件产生意外影响,这些数据应由用户更新,而不是在正常模块更新过程中更新(有关详细信息,请参阅第六章 管理模块数据中的使用noupdate和forcecreate标记一节)。在用户界面没有这种风险,但这可能在命令行中出现。
更多……
处理依赖关系时要小心。考虑一个实例,我们希望安装sale、sale_stock和sale_specific插件,其中sale_specific依赖于sale_stock,而sale_stock依赖于sale。要安装所有三个,只需安装sale_specific,因为它将递归安装sale_stock和sale依赖。要更新所有这三个,只需更新sale,因为将递归更新反向依赖项sale_stock和sale_specific。
管理依赖关系的另一个棘手部分是在向已安装版本的插件添加依赖时。继续使用上面的例子。假设在sale_specific中添加了对stock_dropshipping的依赖。更新sale_specific插件不会自动安装新依赖项,请求安装sale_specific也不会。这时,可能会收到非常讨厌的错误消息,因为插件的Python代码未成功加载,但插件的数据和数据库中的模型表忆存在。为解决此问题,需要停止实例并手动安装新依赖项。
从GitHub安装插件模块
GitHub 是一个很好的第三方插件模块来源。许多 Odoo 合作伙伴使用 GitHub 分享他们内部维护的插件模块,Odoo 社区协会 (OCA) 也在 GitHub 上共同维护了几百个插件模块。在开始编写自己的附加模块之前,请检查是否已经存在可以直接使用或作为初始开发的模块。
本节将展示如何从 GitHub 克隆 OCA 的 partner-contact 项目,并在我们的实例中启其包含的插件模块。
准备工作
假设我们想在客户(合作伙伴)表单中添加新字段。默认情况下,Odoo 客户模型没有性别字段。如想添加性别字段,需要创建一个新模块。所幸,有人在邮件列表中告诉你关于 partner_contact_gender 插件模块的信息,该模块由 OCA 作为 partner-contact 项目的一部分进行维护。
本节中使用的路径反映了标准化实例目录布局一节中建议的布局。
操作步骤
执行以下步骤安装 partner_contact_gender:
- 进入项目目录:
1$ cd ~/odoo-dev/my-odoo/src - 在 src/ 目录中克隆 partner-contact 项目的 17.0 分支:
12$ git clone --branch 17.0 \https://github.com/OCA/partner-contact.git src/partner-contact - 更改插件模块路径新增该目录,并更新实例的插件模块列表(参考本章中的配置插件模块路径一节和上一章的更新插件模块列表一节)。instance.cfg 文件的 addons_path 行如下所示:
1234addons_path = ~/odoo-dev/my-odoo/src/odoo/odoo/addons, \~/odoo-dev/my-odoo/src/odoo/addons, \~/odoo-dev/my-odoo/src/partner-contact, \~/odoo-dev/local-addons - 安装 partner_contact_gender 插件模块(如果不知道如何安装模块,请参阅上一节中的安装和升级本地插件模块)。
工作原理
所有 OCA 代码库中的插件模块都位于单独的子目录中,这与 Odoo 对插件模块路径中目录的要求一致。因此,只需将代码库克隆到某处并将该位置添加到插件模块路径即可。
更多…
一些维护者采用不同的方式,在仓库根目录下每个仓库只有一个插件模块。这时,需要创建一个新目录,添加到插件模块路径中,并将需要的所有维护者的插件模块克隆到该目录中。记得在每次添加新仓库克隆时更新附加模块列表。
应用对插件的更改
GitHub 上的大多数插件模块都在不断变化,不遵循 Odoo 对其稳定版本的规定。它们可能会接收到 bug 修复或增强功能,包括所提交的issue或功能请求,这些更改可能会引入数据库架构变化或数据文件和视图的更新。本节将讲解如何安装更新版本。
准备工作
假设你报告了 partner_contact_gender 的一个问题,并收到通知说问题已在 partner-contact 项目的 17.0 分支的最新修订版中解决。此时,你可能想要使用这个最新版本更新实例。
操作步骤
要通过 GitHub 应用源代码修改到你的插件模块,请执行以下步骤:
- 停止使用该插件模块的实例。
- 如果是生产实例,请先备份(参考第一章 安装Odoo开发环境中的管理 Odoo 服务数据库一节)。
- 切换到克隆 partner-contact 的目录:
1$ cd ~/odoo-dev/my-odoo/src/partner-contact - 为项目创建本地标签,以便在出现问题时可以回滚到该版本:
12$ git checkout 17.0$ git tag 17.0-before-update-$(date --iso) - 获取最新版本的源代码:
1$ git pull --ff-only - 更新数据库中的 partner_contact_gender 插件模块(如果不知道如何更新模块,请参考安装和升级本地插件模块一节)。
- 重启实例。
工作原理
通常,插件模块的开发者会不时发布最新版本的插件模块。此更新通常包含 bug 修复和新功能。这里,我们将获取附加模块的新版本并在我们的实例中更新它。
如果 git pull --ff-only
失败,可以使用以下命令恢复到以前的版本:
1 |
$ git reset --hard 17.0-before-update-$(date --iso) |
然后,可以尝试 git pull
(不带 --ff-only
),这将产生合并,但这意味着你在插件模块上有本地更改。
补充
如果更新步骤失败,请参考第一章 安装Odoo开发环境中的从源代码更新 Odoo一节以获取还原的步骤。记住始终在生产数据库的副本上测试更新。
应用和测试拉取请求(PR)
在 GitHub 世界中,PR 是开发者提出的一种请求,以便项目的维护者可以新增一些新的开发。这种 PR 可能包含 bug 修复或新功能。这些请求在被合并到主分支之前会进行审查和测试。
本节讲解如何将 PR 应用于你的 Odoo 项目以测试改进或 bug 修复。
准备工作
如前所述,假设你报告了 partner_address_street3 的一个问题,并收到通知说问题在一个 PR 中解决了,该 PR 尚未合并到项目的 17.0 分支。开发者要求你验证 PR #123 中的修复。你需要用此分支更新一个测试实例。
不要直接在生产数据库上测试这些分支,因此首先使用生产数据库的副本创建一个测试环境(参见第一章 安装Odoo开发环境)。
操作步骤
执行以下步骤应用并测试 GitHub PR 的插件模块:
- 停止实例。
- 切换到克隆 partner-contact 的目录:
1$ cd ~/odoo-dev/my-odoo/src/partner-contact - 为项目创建本地标签,以便在出现问题时可以回滚到该版本:
12$ git checkout 17.0$ git tag 17.0-before-update-$(date --iso) - 拉取 PR 分支。最简单的方法是使用 PR 的编号,开发者应已将编号告知你。在我们的例子中, PR 编号是 123:
1$ git pull origin pull/123/head - 更新数据库中的 partner_contact_gender1 插件模块并重启实例(如果不知道如何更新模块,请参考安装和升级本地插件模块一节)。
- .测试更新——尝试重现你的问题,或测试你想要的功能。
如果不行,在 GitHub 的 PR 页面上评论,说明你做了什么以及没有成功的地方,以便开发者可以更新 PR。
如果成功了,也在 PR 页面上说明;这是 PR 验证过程中的重要部分,可加快合并到主分支的速度。
工作原理
我们正在使用 GitHub 的一个功能,该功能允许通过编号拉取 PR,使用的是 pull/nnnn/head
分支名,其中 nnnn
是 PR 的编号。git pul
命令将合并远程分支到我们的分支中,在我们的代码库中应用更改。之后,我们更新插件模块,测试它,并向变更的作者报告失败或成功情况。
更多信息
如果你想同时测试同一仓库中的不同 PR,可以重复本节的第 4 步。如果对结果非常满意,可以创建一个分支保留应用更改后的结果:
1 |
$ git checkout -b 17.0-custom |
使用不同的分支将有助你记住使用的不是来自 GitHub 的版本,而是自定义版本。
注:git branch命令可以列出你在仓库中拥有的所有本地分支。
然后,如果需要应用 GitHub 上 17.0 分支的最新修订,需要不使用 --ff-only
进行拉取:
1 |
$ git pull origin 17.0 |