Odoo的开发模式和基本概念
Odoo提供了一个快速开发的框架尤其是比较适合商业场景的一些应用开发,这些应用通常都是对一些业务上的记录进行一些增删改查的工作。不仅如此,Odoo还提供了丰富的组件用以制作用户的交互,如看板、日历等日常功能。
以下我们分为五个板块介绍Odoo:
首先,我们整体的对Odoo框架做一个整体的概览,设置开发环境,并生成自己的第一个Odoo应用;当整体熟悉了 Odoo的主要组件后,我们将深入,更细节地了解Odoo的三层业务架构,这三大板块分别是模型层、业务逻辑层、和表现层;当我们建立了自己的应用后,最后我们需要测试、发布到一个生产环境并维护。
在这个章节中,我们会快速开始,在未搭建开发环境钱,首先建立Odoo的Web用户界面。我们将会学习一些关于Odoo架构的东西,帮助我们理解哪些组件比较适合,然后我们会建立一个简单的图书馆应用,如何在现有模型中增加字段,如何新增新的模型,并为其新增自定义的用户界面,使其可用。
在我们亲身使用开发者模式前,首先在一个更高的层级,看看Odoo的整体架构。
Odoo 架构
Odoo是一个多层的架构,我们看到的主要有一下三层:数据、逻辑和表现层
数据层是最底的一层,它负责数据的存储和持久化,Odoo使用 PostgreSQLSever来完成这一层工作,PostgreSQL是唯一被支持的关系型数据库,这是设计者的选择,其他的数据库如MySQL等都不受支持,其他诸如文档、图像等,通常以文件系统方式存储。
逻辑层是由Odoo服务器控制,负责所有对数据层的交互。在正常情况下,只允许该层直接访问数据库以保证数据安全与同步。在Odoo的核心,有一个ORM(对象关系模型)引擎,ORM提供提供丰富的API以供新增的模块和数据交互使用。
举个例子,合作商数据实体,像顾客和供应商,在ORM中作为一个模型,这个模型是一个Python的对象,支持多种的交互方法,例如,create方法可以新建合作商记录,read方法可以查询当前的记录和详细数据。这些在对象里的方法可以实现特定的业务逻辑,例如create方法可以设置某些默认值或者做某些验证的规则,read方法可能支持某些字段的计算,为用户的操作设定不同的权限。
表现层作为展现数据与用户交互.它是一个负责对所有用户操作执行的客户端响应。这个客户端通过与ORM的API交互去完成读、写、验证或执行其他的一些操作,通过远程方法调用(RPCS)去呼叫ORM的API方法调用。这些操作会发到odoo服务器做处理,然后将结果返回到客户端以做进一步处理。
在表现层里,Odoo提供了一个全功能开箱即用的Web客户端,这个Web客户端支持业务逻辑需要的所有属性如:登录会话,导航菜单,数据列表,表单等等。虽然全局的外观不像一个前端人员设想的那样可定制化,但是它已经可以很轻松地区创建一个风格统一的用户功能模块。
其中一个补充的显示层是集成的网站框架,他提供一个完成灵活性的页面新建可准确地完成用户的交互。像其他CMS框架一样,旨在减少一些工作量和技术开发。这个网站框架支持Web控制器实现特定的逻辑代码,使其余模型内的逻辑保持分离,前段开发人员可以有更大的自由发挥空间。
由于Odoo服务器API的开放性,以致在几乎所有的平台和编程语言的客户端实现也是可行的。利用Odoo的数据和逻辑层实现逻辑,为用户提供特定的用户界面,如构建桌面应用程序,手机应用程序。
Odoo还有一个特别的第三方客户端例子叫ERPpeek,他是一个命令行客户端。允许你链接远程的Odoo服务器实现交互。这对于有经验的Odoo开发人员和系统管理员来说,使用它去做服务器上的数据,脚本检查等高级操作与维护是非常有用的。后续我们将在第8章介绍ERPpeek, 即与其他系统集成外部API。
开发者模式
许多Odoo的自定义都可以直接从用户界面进行。
这是更改应用程序一个非常快速的方法。它可以做一些小修改,例如增加一个字段,或者做一些较大的自定义,入建立几个模型,视图和菜单项。
与后面章节讲述的,使用变成工具完成自定义的方式相比,这些通过用户UI进行的自定义有不少的限制。举个例子,我们不能添加或扩展ORM的方法,尽管自动化操作可以作为替代方法使用,但他们不容易集成到结构化的开发工作流中,例如运行自动化测试或部署到多个环境中、再如质量保证,预生产和生产。
Odoo10.0的时候引入了Odoo Studio,这是一个应用程序设计器,可以从用户界面创建并进行定制。我们不在这里讨论Odoo Studio, 它虽然是一个用户体验友好的前端,但正如我们在本章节中介绍到的,它的自定义会得到相同的限制。Odoo Studio确实包含一个很重要的特性,就是很方便的到处模块进行定制。这对于高级用户在SaaS实例或更简单的自建平台环境中非常有用。
本书的其余部分将介绍如何以结构化方式对ODOO进行二次开发,用代码编辑器创建附加模块。
但在本章中,我们先用开发者模式特性直接在Web用户界面对界面进行定制,因为对于开发人员来说,了解和使用这些工具是非常重要的。
但更重要的,我们通过这些练习,需要完成一个目标:更好地理解Odoo应用程序的层次结构,以及他们的组件是如何组织的。
废话不多说,我们开始来折腾这些工具吧。
图书馆项目介绍
我们会用一个简单的项目来介绍这些开发工具:我们会新建一个简单的图书馆应用,这个应用主要是帮我们去记录书本和他们的作者。它可以管理作家的列表和这些书是哪位作家创作的。
我们的图书馆应用需要两个模型:作家和书本。这两模型属于多对多的对应关系:每一个作家可以有多本书,每一本书可以有多个作家。
Odoo已经提供了技术名称为res.partner内置的伙伴关系模型,以表示人员、组织和地址。例如客户、供应商、联系人和应用程序用户都是合作伙伴。我们使用这个模型用于图书馆应用的作者,将使事情简单很多。我们只需要在这个模型上增加一个是否为“作家”的标记,以及增加一个仅显示作家的菜单即可。
而对于书本,我们将创建一个全新的模型,相应的表达,列表视图以及访问它们的菜单项。
创建一个工作数据库
我们需要在一个Odoo测试数据库上工作。
在第二章(安装与部署开发环境),我们将会介绍如何通过源码安装Odoo,并建立自己的开发环境。在这里我们先略过。我们现在现有的ODOO服务器上直接使用用户的UI开始。
如果你还没有一个可用的Odoo已安装的版本,你可以先在odoo.com建立一个测试数据库来完成本章节。Odoo.com提供企业版的用户接口,用户界面和我们提供的截图有些许不一致,但这并没太大问题。要创建一个新的数据库,你可能会被问到选择一个启动应用程序,在这一章中没有特定的应用程序需要遵循,但如果你不确定选什么,选CRM就可以了。
Odoo遵循一个核心开放的商业模型, 产品分为社区版和企业版两个版本发布。企业版是在社区版基础上构建的,它添加了一些高级功能,包括改进的用户界面。在Odoo.com,你将使用企业版,在公共Github仓库,你可以找到社区版。虽然这两个版本外观看起来不同,但他们只是表面上的改变,两个版本的用户界面特性是一样的
现在,我们通过浏览器登录并进入Odoo的数据库。对于Odoo在线,地址会如http://<mydbname>.odoo.com。对于自己部署的实例,地址将会是http://<server-address>:8069。8069是Odoo的默认端口,如果你安装时使用了不同的端口,应修改成对应的端口号。
我们将使用目录里的应用程序——联系人,所以我们首先安装它,如果你还安装,打开顶部菜单,找到联系人,点击安装。
现在我们可以使用这个实力开始工作了,接下来的一步是激活开发者工具,这让我们能访问到Odoo的内部构件。
激活开发者模式
在设置界面的右下角,你可以找到激活开发者模式的链接,点击它,可以在浏览器窗口启用一些开发者模式的特性。
!对于Odoo9.0或之前的版本,开发者模式在用户菜单下的,“关于”对话框窗口中激活,在网页界面的右上角
我们还有一个激活开发者模式(带有资源包)的选项,它所做的是为了防止网页客户端压缩网页的资源包,这对于调试网页是非常有用的,牺牲了速度为代价。(下载的文件变大了,自然网页加载的速度会变慢)
为了加载得更快,Web客户端会将JavaScript和CSS的资源包进行压缩,这样的话,就会对网页调试带来不便。激活开发者模式(带资源包)选项会防止文件压缩,将网页资源包单独的,为被压缩的加载出来。
TIPS:你也可以不进行设置而启用开发者模式,只需编辑当前的URL后面加入?debug,或者?debug=assets ,例如,http://myserver/web#home将被更改为http://myserver/web?debug#home。虽然没用点击启用它的连接,但前端框架也支持调试标志,使用?debug=assets 添加到对应的URL来禁止避免对Web前端的资源包进行压缩。但要注意,导航到其他页面的时候,这个参数不会进行持久化。
当开启了开发者模式,我们将会看见有两个额外的菜单可用:
- Debug菜单,位于顶部菜单右侧的Debug图标,在用户名和头像前面。
- 技术菜单条目,在设置应用里
开发人员模式还支持有关表单字段的其他信息,鼠标指针停留在一个字段上时,工具会提示它的技术信息
我们将在下一步部分介绍和使用这些开发者模式的特性。
在一个现有的模型上增加字段
增加一个定制字段是一个很常规的定制操作,可以直接通过用户UI进行,不需要新增一个自定义模块。
对于我们的图书馆应用,我们需要增加一个是否为作家的一个字段。作为基础模型:合作伙伴模型的标记。以此可以列出所有的作家。
我们可以通过“设置”应用来完成这项操作,在 “技术->数据库结构->模型” 菜单项目,查找到 res.partner 模型,模型描述为“联系人”的模型。点击打开相应的表单视图,你就可以看到合作伙伴模型具体的属性,包括所有的字段列表:
现在,我们可以在列表在底部点击新增一行了,这时,一个弹出窗口将会显示。
让我们进行一下配置:
- 字段名称:x_is_book_author
- 字段标签: Is Book Author?
- 字段类型:布尔值
这个字段必须从x_开始。这时通过UI直接对模型新增字段强制的。对附加模块没有这个限制。
就这样,点击保存和关闭,我们新的字段就被添加到字段列表里面了。这个模型可能有超过80个字段,你可能需要通过导航翻到下一页才能看到他,使用列表右上角的向右箭头即可。
现在,点击左上角的保存按钮,保存这些修改。
我们现在新的字段已经对合作伙伴模型可用了,但对于用户它还是不可见的,因此我们需要将他加入到视图中。
但是,在合作伙伴或叫联系人模型表单里,点击视图的选项卡,我们可以看到所有定义在res.partner模型上的视图。你可以看到,每一个视图是一个数据库的记录。修改和增加视图记录的结果是,你会在页面重载的的时候看见它。
在视图列表中有些重要的事情需要注意。
我们可以看见有多个视图类型,如表单,树形,搜索,或者看板。搜索视图实际上是对右上角搜索栏的可用筛选器定义。其他的视图类型是不同的数据显示方式,其中比较基础的树形(用于列表视图)和窗体(用于详细信息)
树形和列表都可以用来引用相同的视图类型,他们实际上是列表,而树形这个名字是因为历史的原因。在过去的列表视图里面曾经有过一个“树”的层次模型。
如果你通过视图类型进行排序,你会注意到相同的视图类型可以有多个定义。实际上,我们可以有几个基本的视图定义,如一个空的继承视图。我们也可以有多个扩展视图,例如,将字段添加到现有表单。
扩展视图可以被其他扩展视图扩展。在这种情况下,最后的扩展应用于前面的扩展都已应用于基本视图之后。
对于res.partner模型,我们看到两种基本的表单形式的客户端操作:res.partner.form 和 res.partner.simplified.form。想这些操作在菜单项目中,可以指定要使用的特定基视图,如果没有任何定义,可以使用序列最少的一个。你可以把它想成默认视图,单击视图行,我们将可以看到带有的视图的详细信息,包括序列值。
要了解用户界面某一处使用特定的视图是什么,我们可以使用Debug菜单去检查它。让我们去试一试,点击联系人,我们会收到一份联系人名单,点击任何卡片,将会显示对应的表单视图。现在,我们点击右上角的调试Debug菜单,选择“编辑视图:表单”选项:
这将显示与我们以前在模型中看到的相同的详细表单,但是实际上视图的定位位置,如你所建。它是res.partner.form 页面视图
在体系架构方面中,我们可以看到带有视图定义XML。我们可以编辑它来添加我们的新字段,虽然这是可行的,但是从长远来看,这不是一个好方法。这个视图属于插件模块,有时进行模块升级,这些自定义将会被覆盖或丢失。我们可以通过外部ID字段,在这种情况下,它是base.view_partner_form。所以我们知道这个视图是属于base模块的。
修改视图的正确方法是创建集成的视图扩展。
首先,我们需要从原始视图中选择一个元素作为扩展点。我们可以通过检查基本视图来选择一个具有name属性的XML元素。大多数情况下,这将是一个<field>元素。这里,我们将选择<field name="category_id" ...>元素。
现在,我们打开Debug菜单,点击编辑表单页面选项,选择继承的视图选项卡,点击底部的“添加明细行”。
弹出窗口会显示,创建:一个视图继承自哪一个?我们将会填写以下信息:
-视图名称:联系人-自定义是否一个作家
-结构:使用下面的XML:
<field name = "category_id" position="after">
<field name = "x_is_book_author" />
</field>
其他重要的栏目,如模型、视图类型、及继承视图,使用默认值即可。
我们现在保存并关闭。在编辑表单视图窗口保存然后关闭它。我们可以看到更改已经剩下,然后我们重载这个表单视图。就是要刷新整个浏览器页面,在大部分的浏览器上,我们可以试用快捷键F5进行刷新。
增加菜单,模型和视图
现在我们新增一个应用功能,而不是扩展现有的一个,我们将继续完成我们的图书馆项目
首先,我们需要新建一个图书馆的顶层菜单,我们现在已经新增了作家菜单条目,下一步,我们将创建一个书本的模型,并且增加一个菜单让用户可以试用它,然后我们可以为书本模型创建列表和表单视图。
创建菜单
现在我们已经有途径去列出作家,它是一个合作伙伴列表,使用作家标记进去区分。
现在,我们需要新增一个作家菜单使其可以打开这个列表,筛选掉一些不是作家的合作伙伴。一个好消息是,我们可以很简单的重用了现有的合作伙伴视图完成这个操作。
在此之前,我们首先要建立一个顶部入口菜单去显示我们的靓仔图书馆应用,下面将包含作家和书籍两个菜单。
我们可以在设置里面找到菜单的定制,在“技术”->“用户界面”-> "菜单项目",使用下面的信息创建一个新的菜单项目:
- 菜单:图书馆
- 上级菜单:(空)
- 动作:(空)
在子菜单选项卡中,点击增加明细行,新增一下一个子菜单信息如下:
- 菜单:图书作者
- 上级菜单:图书馆(默认值)
- 动作:选择 ir.actions.act_window, 在选项列表上右击创建并编辑,开启一个对话框去创建关联的视窗操作。为视窗操作设置以下的值
- 动作名称: 图书作者
-
对象: res.partner (目标模型的技术名称)
保存所有表单的信息,图书馆应用的菜单树已经可以使用了。
我们重新加载页面,就可以看到菜单的更改。我们可以看到生成了多级的菜单结构,子菜单项目有关联的动作,定义它在选中时发生什么。这个动作的名称将用作呈现视图的标题。
这里有多种动作可选,最重要的动作为窗口、报表和服务器动作。窗口动作是最常见的视图,在浏览器终端显示视图。报表动作是用作运行报表。服务器动作是用作定义自动化任务。
此时,我们关心的是用于显示视图操作的窗口动作。
我们刚创建的图书馆作者菜单项使用了一个窗口操作,它是直接从菜单表单创建的,我们可以查看和从设置|技术|动作菜单选项编辑它,在特殊情况下,我们对窗口操作菜单更感兴趣。
碰巧我们创建的图书作者太简单了,而且确实如此。不要执行我们想要的,它将于所有合作伙伴一起打开一个列表,不管他们是否这本书的作者?集合。我们需要解决这个问题。
打开窗口动作菜单项,查找我们最近创建的图书作者操作并编辑它,我们关心筛选器的部分,在“常规设置”选项卡内。
TIP:在许多情况下,使用Debug菜单中的Edit Action选项更方便,它提供编辑用于访问当前视图窗口操作的便捷快捷方式。
域值字段可以有一个表达式,改表达式定义要显示的记录的过滤器,这种“域表达式”遵循特定的odoo语法,后面的章节对此进行解释,现在我们知道它是一个三胞胎列表就足够了。
在我们的例子中,我们使用“域值”的表达式是:
| [('x_is_book_author', '=', True)]
为了可用性,我们还想要创建新的记录有是否作者标记。我们可以在试图上通过设置默认值操作来完成,这是通过上下文方式完成的,上下文是Odoo传递会话信息的方式,包括要使用的默认值。后面几章将详细讨论它,现在我们只需要知道它是一个键值对字典。以default_前缀的值为相应字段提供默认值。
在我们的例子中,上下文值需要的表达式是:
| {'default_x_is_book_author': True}
就是这样。如果我们现在尝试Library | Book Authors菜单选项,它应该只列出Is Book Author的合作伙伴?检查标志,如果有的话。如果我们试着创建一个新的图书作者,我们会看到那个是图书作者吗?默认情况下,复选框将被方便地选中。
我们使用的域过滤器不能被用户删除。可以设置可以删除的默认过滤器,使用上下文启用默认搜索过滤器。这是通过search_default_键完成的,如第9章“后端视图—设计用户界面”中所述。
创建一个自定义模型
我们现在有一个图书馆的以及菜单,以及有一个作者的菜单项,是时候添加一个图书菜单去管理图书的记录。
让我们重新查询,在设置-> 技术->数据结构->模型菜单,点击新建,填写模型的信息如下:
- 模型描述:Book
- 模型: x_library_book
我们先保存