第 2 章:开发环境搭建

根据预期的使用场景,安装 Odoo 有多种方式。无论是 Odoo 社区的开发者还是 Odoo 员工,首选的方式都是源码安装(从源代码运行 Odoo)。

准备环境

首先,按照贡献指南中的 环境设置 一节准备您的环境。

到此为止,您应该已经下载了源代码并得到两个本地仓库,一个对应 odoo/odoo,一个对应 odoo/enterprise。这些仓库被设置为将更改推送到 GitHub 上预定义的 fork。当您开始为代码库做贡献时,这会非常方便;但就本教程的范围而言,我们不希望用培训材料污染它们。因此,我们在第三个仓库 odoo/tutorials 中开发您自己的模块。与前两个仓库一样,它也将是 addons-path 的一部分,addons-path 引用了所有包含 Odoo 模块的目录。我们将在这个仓库中创建第一个模块!

Note

该仓库中还包含一些基础模块,将在其他教程中使用。

  1. 按照与 odoo/odoo 和 odoo/enterprise 仓库相同的流程,使用以下命令将 odoo/tutorials 仓库克隆到您的计算机上:

    $ git clone git@github.com:odoo/tutorials.git
    
  2. 配置您的分支库(fork)和 Git,将更改推送到您自己的分支库而不是主代码库。如果您在 Odoo 工作,请将 Git 配置为推送到 odoo-dev 账号上创建的共享分支库。

    1. 访问 github.com/odoo/tutorials 并点击 Fork 按钮,在您的账号上创建该仓库的分支库。

    2. 在下面的命令中,将 <your_github_account> 替换为您创建分支库所用的 GitHub 账号名称。

      $ cd /TutorialsPath
      $ git remote add dev git@github.com:<your_github_account>/tutorials.git
      

大功告成!您的环境现在已经可以从源码运行 Odoo,并且您已成功创建了一个用作插件目录的仓库。这让您可以把工作成果推送到 GitHub。

Important

仅限 Odoo 员工:

  1. 请务必仔细阅读 做出您的第一个贡献。特别是,您的分支名称必须遵循我们的命名约定。

  2. 在您将第一个更改推送到 odoo-dev 上的共享分支库后,创建一个 PR。请在 PR 标题中写上您的四字缩写(例如 “abcd - Technical Training”)。

    这样您就可以分享即将开展的工作,并从导师那里获得反馈。为了保证持续的反馈循环,我们建议您每完成教程的一个章节就推送一个新提交。请注意,PR 会随您推送到 odoo-dev 的提交自动更新,无需打开多个 PR。

  3. 在 Odoo,我们广泛使用 Runbot 来进行 CI 测试。当您将更改推送到 odoo-dev 时,Runbot 会创建一个新的构建并测试您的代码。登录后,您将能够看到您的分支所在的 Tutorials project。

Note

仓库在您文件系统上的具体位置并不关键。不过,为了简单起见,我们假设您已将所有仓库克隆到了同一个目录下。如果不是这样,请确保相应调整以下命令,给出从 odoo/odoo 仓库到 odoo/tutorials 仓库的合适的相对路径。

运行服务器

用 odoo-bin 启动

所有依赖都设置好后,就可以通过运行服务器命令行界面 odoo-bin 来启动 Odoo。

$ cd $HOME/src/odoo/
$ ./odoo-bin --addons-path="addons/,../enterprise/,../tutorials" -d rd-demo

有多种 命令行参数 可用于运行服务器。在本次培训中,您只会用到其中的一部分。

-d <database>

将要使用的数据库。

--addons-path <directories>

以逗号分隔的目录列表,模块存放在这些目录中。系统会扫描这些目录以查找模块。

--limit-time-cpu <limit>

限制工作进程(worker)为每个请求使用不超过 <limit> 秒的 CPU 时间。

--limit-time-real <limit>

限制工作进程处理一个请求的时间不超过 <limit> 秒。

Tip

  • 在调试源代码时,可以使用 --limit-time-cpu 和 --limit-time-real 参数来避免工作进程被终止。

  • 您可能会遇到类似 AttributeError: module '<MODULE_NAME>' has no attribute '<$ATTRIBUTE'> 的错误。此时,您可能需要使用 $ pip install --upgrade --force-reinstall <MODULE_NAME> 重新安装该模块。
    如果多个模块都出现此错误,您可能需要使用 $ pip install --upgrade --force-reinstall -r requirements.txt 重新安装所有依赖。
    您也可以清除 Python 缓存来解决这个问题:
    $ cd $HOME/.local/lib/python3.8/site-packages/
    $ find -name '*.pyc' -type f -delete
    
  • 其他常用参数还有:

    • -i:在运行服务器之前安装一些模块(逗号分隔的列表)。这相当于在用户界面中进入 应用,然后从那里安装模块。

    • -u:在运行服务器之前更新一些模块(逗号分隔的列表)。这相当于在用户界面中进入 应用,选择一个模块,然后从那里升级它。

Note

目前您无法将 ../technical-training-sandbox 添加到您的 addons-path,因为它是空的,会导致无效的 addons-path 文件夹错误,但稍后您必须把它加回来!

登录 Odoo

在浏览器中打开 http://localhost:8069/。我们推荐使用 Chrome、Firefox 或任何其他带有开发工具的浏览器。

要以管理员用户身份登录,请使用以下凭据:

  • 邮箱:admin

  • 密码:admin

启用开发者模式

开发者模式或调试模式在培训中很有用,因为它可以访问额外的(高级)工具。在后续章节中,我们始终假定您已启用开发者模式。

现在 启用开发者模式。选择您喜欢的方式即可;它们都是等效的。

Note

只有在至少安装了一个应用后,才能访问设置界面的主页。在下一章中,您将开始安装自己的应用。

额外工具

实用的 Git 命令

以下是一些对日常工作很有用的 Git 命令。

  • 切换分支:
    切换分支时,两个仓库(odoo 和 enterprise)必须保持同步,即两者都需处于同一分支上。
    $ cd $HOME/src/odoo
    $ git switch 16.0
    
    $ cd $HOME/src/enterprise
    $ git switch 16.0
    
  • 拉取并变基(rebase):

    $ cd $HOME/src/odoo
    $ git fetch --all --prune
    $ git rebase --autostash odoo/16.0
    
    $ cd $HOME/src/enterprise
    $ git fetch --all --prune
    $ git rebase --autostash enterprise/16.0
    

代码编辑器

如果您在 Odoo 工作,您的许多同事都在使用 VSCode、VSCodium (开源等效版本)、PyCharm 或 Sublime Text。不过,您可以自由选择自己偏好的编辑器。

正确配置您的 linter 很重要。使用 linter 可以通过显示语法和语义方面的警告或错误来帮助您。Odoo 源码尽量遵循 Python 和 JavaScript 的标准,但其中有些规范可以忽略。

对于 Python,我们使用 PEP8,但忽略以下选项:

  • E501:行太长

  • E301:应有一个空行,实际为 0

  • E302:应有两个空行,实际为 1

对于 JavaScript,我们使用 ESLint,您可以在这里找到一个 配置文件示例。

PostgreSQL 管理工具

您可以像前面演示的那样使用命令行来管理 PostgreSQL 数据库,也可以使用 pgAdmin 或 DBeaver 等图形界面(GUI)应用。

要将图形界面应用连接到您的数据库,我们建议您使用 Unix 套接字(socket)进行连接。

  • 主机名/地址:/var/run/postgresql

  • 端口:5432

  • 用户名:$USER

Python 调试

在遇到 Bug 或想弄清楚代码如何运行时,简单地打印输出内容就很有帮助,但一个合适的调试器能节省大量时间。

您可以使用经典的 Python 库调试器(pdb、pudb 或 ipdb),也可以使用您编辑器自带的调试器。

在下面的示例中我们使用 ipdb,但使用其他库时过程也类似。

  1. 安装该库:

    pip install ipdb
    
  2. 放置触发点(断点):

    import ipdb; ipdb.set_trace()
    

    Example

    def copy(self, default=None):
        import ipdb; ipdb.set_trace()
        self.ensure_one()
        chosen_name = default.get('name') if default else ''
        new_name = chosen_name or _('%s (copy)') % self.name
        default = dict(default or {}, name=new_name)
        return super(Partner, self).copy(default)
    

以下是命令列表:

h(elp) [command]

如果没有提供参数,则打印可用命令的列表。如果以命令作为参数,则打印关于该命令的帮助信息。

pp expression

expression 的值会使用 pprint 模块美观地打印出来。

w(here)

打印堆栈回溯,最新的帧位于底部。

d(own)

在堆栈回溯中把当前帧向下移动一层(移到更新的帧)。

u(p)

在堆栈回溯中把当前帧向上移动一层(移到更早的帧)。

n(ext)

继续执行,直到到达当前函数的下一行或该函数返回。

c(ontinue)

继续执行,仅在遇到断点时停止。

s(tep)

执行当前行。在第一个可能的时机停下(在被调用的函数中,或当前函数的下一行)。

q(uit)

退出调试器。正在执行的程序将被中止。

现在您的服务器已经在运行,是时候开始 编写您自己的应用 了!