第三章 Odoo 12 开发之建立第一个 Odoo 应用

Odoo 开发一般都须要建立本身的插件模块。本文中咱们将经过建立第一个应用来一步步学习如何在 Odoo 中开启和安装这个插件。咱们将从基础的开发流学起,即建立和安装新插件,而后在开发迭代中更新代码来进行升级。html

Odoo 采用类 MVC(Model-View-Controller)的结构,咱们将深刻到各层来实施一个图书应用。本文主要内容有:前端

  • 建立一个新的模块,用来实施相关功能
  • 添加应用的特性功能:顶级菜单项和安全组
  • 添加一个一开始会失败但在项目完成时成功运行的自动化测试
  • 实施模型层,定义应用的数据结构和相关访问权限
  • 实施后台视图层,编写内部用户界面
  • 实施业务逻辑层,支持数据验证和自动化
  • 实施 web 层,展现访客和内部用户的用户界面

 

系统准备

本文要求安装了 Odoo 服务并可经过命令行启动服务来进行模块安装和运行测试之类的操做。若是尚未相关环境,请参照本系列文章第二篇Odoo 12开发之开发环境准备git

本文中咱们将从零开始建立第一个 Odoo 应用,无需额外的代码。本文代码可经过 GitHub 仓库进行查看。github

概览图书项目

为更好地在本文中探讨,咱们将使用一个现实中可使用的学习项目。一块儿来建立一个管理图书库的 Odoo 应用。该项目将在后续文章中持续使用,每篇文章都会进行一次迭代,为应用添加新的功能。本文中将建立图书应用的第一个版本,第一个功能是实现图书目录。web

图书将包含以下数据:算法

  • 标题
  • 做者
  • 出版社
  • 发行日期
  • 封面图
  •  ISBN:包含检查 ISBN是否有效的功能
  • 有效性标记;标识图书是否已对公众发布

图书目录可由图书管理员编辑,对图书操做者则仅有可读权限。该目录可经过公共网页访问,仅显示已发布图书。就是这样一个简单的项目,但提供有用的功能,足以让咱们了解 Odoo 应用的主要构件。数据库

建立新的插件模块

一个插件模块是包含实现一些 Odoo 功能的文件夹,能够添加新功能或修改已有的功能。插件目录必须含有一个声明或描述文件__manifest__.py,以及其它模块文件。编程

一部分模块插件在 Odoo 中以app的形式出现,一般都会带有顶级菜单项。它们为 CRM 或 HR 这样的功能区添加核心元素,所以在 Odoo 应用菜单中会高亮显示。另外还有一些非应用模块插件通常为这些应用添加功能。若是你的模块为 Odoo 添加新的或重要的功能,通常应该是app。而若是模块仅修改应用的功能,那么就是一个普通的插件模块。sublime-text

要建立新模块,须要:api

  1. 确保操做的目录是 Odoo 的 addons 路径
  2. 建立模块目录,并包含声明文件
  3. 可选择为模块添加一个图标
  4. 如打算对外发布,为模块选择一个证书

而后咱们就能够安装模块了,肯定模块在 Odoo 服务中可见并正确安装它。

准备 addons 路径

一个插件模块是一个含有 Odoo 声明文件的目录,它建立一个新应用或为已有应用添加功能。addons模块的路径是一系列目录,Odoo 服务能够在这里查找插件。默认addons包含odoo/addons 中存放的 Odoo 自带的官方应用,以及在odoo/odoo/addons目录中提供核心功能的 base 模块。

咱们应将本身建立的或应用市场及其它地方下载的模块放到指定的目录中。要使得 Odoo 服务可以找到这些应用,须要这些目录添加到 Odoo 的 addons 路径中。

根据咱们在Odoo 12开发之开发环境准备所建立的项目,Odoo 的代码存放在~/odoo-dev/odoo/目录下。最佳实践告诉咱们应在自有目录下添加代码,而不该与 Odoo 源代码混在一块儿。因此要添加自定义模块,咱们将在 Odoo 同级建立目录~/odoo-dev/custom-addons并添加到 addons 路径中。要添加该目录至 addons 路径,执行以下命令

注:若有报错参照Odoo常见问题汇总开发类错误处理001

–save 参数将选项保存至配置文件中,这样咱们就无需在每次启动服务时输入参数,只需运行./odoo-bin 便可使用上次使用的参数。能够经过-c 参数指定文件来使用或保存配置项。仔细查看输出的日志,能够看到INFO ? odoo: addons paths:[…] 一行中包含custom-addons目录。

如需使用其它目录也请添加至 addons 路径,好比有~/odoo-dev/extra 目录中包含需用到的目录,则需经过以下方式设置–addons-path参数:

如今咱们须要让 Odoo 实例能识别新模块。

小贴士:以上使用的是相对路径,但在配置文件中需使用绝对路径,–save 参数会自行进行转化。

建立模块目录和声明文件

如今就准备好了~/odoo-dev/custom-addons目录,已正确添加至 addons 路径,Odoo 也就能够找到这里的模块。Odoo 自带一个scaffold命令可自动建立新模块目录,其中会包含基础结构。此处并不会使用该命令,而是手动建立。经过如下命令能够了解scaffold用法:

Odoo 模块目录需包含一个__manifest__.py描述性文件,同时还须要是可导入的包,因此还应包含__init__.py文件。

ℹ️在老版本中,该描述性文件为__openerp__.py或__odoo__.py,这些名称已过期但仍可以使用。

模块目录名是其技术名称,咱们使用library_app,技术名称应是有效 Python 标识符,即以字母开头且仅能包含字母、数字和下划线。执行以下步骤来初始化新模块:

一、经过命令行,咱们能够添加一个空的__init__.py 文件来初始化模块:

二、下面添加声明文件,其中应包含一个 Python 字典,有几十个可用属性。其中仅 name属性为必填,但推荐同时添加 description 和 author 属性。在__init__.py 同级建立__manifest__.py 文件,添加如下内容:

depends 属性能够是一个包含所用到的模块列表。Odoo 会在模块安装时自动安装这些模块,这不是强制属性,但建议使用。若是没有特别的依赖,能够添加内核 base 模块。应注意将全部依赖都在此处列明,不然,模块会因缺乏依赖而报错或出现加载错误(若是碰巧依赖模块在随后被加载了)。

咱们的应用无需依赖其它模块,因此本处使用了 base。为保持简洁,这里仅使用了几个基本描述符键:

  • name:插件模块标题字符串
  • description:功能描述长文件,一般为RST格式
  • author:做者姓名,本处为一个字符串,能够是逗号分隔的一系列姓名
  • depends:一个依赖插件模块列表,在模块安装时会先安装这些插件
  • application:一个布尔型标记,表明模块是否在应用列表中以 app 展示

description可由模块顶层目录中的README.rst或README.md代替,若是二者都不存在,将使用声明文件中的description。

在真实场景中,建议也同时使用其它属性名,因它们与 Odoo 的应用商店有关:

  • summary:显示为模块副标题的字符串
  • version::默认为1.0,应遵照版本号规则。建议在模块版本号前加上 Odoo 版本,如12.0.1.0
  • license::默认为LGPL-3
  • website:了解模块更多信息的 URL,能够帮助人们查看更多文档或提供文件 bug 和建议的跟踪
  • category::带有模块功能性分类字符串,缺省为Uncategorized。已有分类可经过安全组表单(位于Settings > Users & Companies > Groups)的 Application字段下拉列表查看(需开启调试模式)

Odoo 12 开发之建立第一个 Odoo 应用

还有如下描述符键:

  • installable:默认为 True,但能够经过设置为 False 来禁用模块
  • auto_install:若设置为 True,在其依赖已安装时会自动安装,用于胶水模块,用于同一实例上两个模块安装后功能的链接。

添加图标

模块可选择添加图标,这对于做为 app 的模块尤为重要,由于在应用菜单中通常都应有图标。要添加图标,须要在模块中添加static/description/icon.png文件。

为简化操做,咱们能够复用 accounting 应用的图标,把odoo/addons/account/static/description/icon.png文件拷贝至customaddons/library_app/static/description目录。可经过以下命令完成:

补充:开启开者发者模式(修改 URL 中web#为web?debug#),点击 Apps > Update Apps List便可搜到咱们建立的应用(下图我使用了自定义的图标)

Odoo 12 开发之建立第一个 Odoo 应用

选择证书(开源协议)

为开发的模块选择证书(开源协议)很是重要,应谨慎考虑其表明着什么。Odoo 模块最经常使用的协议是LGPL(GNU Lesser General Public License)第3版(LGPL v3.0)和AGPL(Affero General Public License)。

LGPL 受权更广,它容许在无需分享相应源码的状况下对代码做出商业修改。AGPL则是一个更严格的开源证书,它要求派生代码及服务托管者分享源码。

了解更多有关 GNU 证书请访问GNU官网

安装新模块

如今咱们已经有了一个简化的模块,尚未任何功能,但咱们能够经过安装它来检查各项是否正常。

要进行这一操做,模块全部的插件目录应对 Odoo 服务可见。能够经过启动 Odoo 服务来进行确认,能够在输出第一行看到显示为odoo: addons paths: xxx 字样,其中会显示在用的插件路径。更多有关插件路径的知识,参见本系列文章第二篇 Odoo 12开发之开发环境准备

要安装新的模块,咱们应在启动服务时指定-d 和-i 参数,-d 指定应使用的数据库,-i 可接收一个逗号分隔的多个待安装模块名。假定开发数据库为dev12,则使用以下命令进行安装:

仔细看日志输出可肯定模块是否能被找到并安装,正确安装对应日志: odoo.modules.registry: module library_app: creating or updating database tables。

更新模块

开发模块是一个不断迭代的过程,咱们会须要应用更新所修改代码并在 Odoo 中可见。能够在后台界面Apps中搜索对应模块并点击 Upgrade 按钮。但若是修改的是 Python 代码,点击升级不会生效,须要先重启服务方可生效。这是由于 Odoo 仅会加载一次 Python 代码,此后的修改就要求进行重启才会生效。

有时,模块中既修改了数据文件又修改了 Python 代码,那么就须要同时进行如上两种操做。这是 Odoo 开发者的常见困惑。幸亏还有更好的方式,最保险的方式是重启 Odoo 实例并应用升级至开发数据库。经过Ctrl + C中止服务实例,而后经过以下命令启动服务并升级library_app模块:

-u(或全称–update)要求使用-d 参数并接收一个逗号分隔的待升级模块集。例如可使用-u library_app,mail。模块升级后,全部依赖该模块的模块也会被升级。这是保持用于扩展功能的继承机制完整性的基础。

Odoo 11中的修改:
直到 Odoo 10.0,要安装新的插件模块,须要在后台客户端菜单中手动更新以对 Odoo 可见。从 11.0开始,模块列表在模块安装或更新时会自动更新。

在本系列文章中,如需应用对模块代码的修改:

  • 添加模型字段时需进行升级。修改 Python 代码(含 manifest 文件)时须要重启服务。
  • 修改XML或CSV文件时,需进行升级。在不肯定时,同时重启服务并升级模块。

在不肯定时,最保险的方式是经过-u参数来重启 Odoo 实例,按下键盘上、下方向键可在使用过的命令间切换。进行这一操做时,咱们常常会使用到 Ctrl+C,向上方向键和Enter 键。

或者要避免这种重复的中止/启动操做,可以使用dev=all选项。这样在保存XML 和 Python文件修改时会自动进行重载,参见本系列文章第二篇 Odoo 12开发之开发环境准备了解更多详情。

建立新应用

一些 Odoo 模块建立新应用,而另外一些则对已有应用添加功能或做出修改。虽然二者的技术组件基本相同,但应用会被预期包含一些特征性元素。咱们建立的是一个图书应用,因此应包含这些元素,它们是:

  • 图标:用于在应用列表中展现
  • 顶级菜单项:其下放置全部的应用菜单项
  • 应用安全组:经过权限访问仅对指定用户开放

添加图标(icon),仅需在模块目录下static/description/子文件夹中放置icon.png文件,前面已经介绍过了。下面咱们来添加应用顶级菜单。

添加应用顶级菜单项

咱们建立的是一个新应用,所以应包含主菜单项,在社区版本中,显示在左侧下拉菜单中,而在企业版中,则做为附加图标显示在应用切换器主界面中。

菜单项是使用 XML 文件中添加的视图组件,经过建立views/library_menu.xml来定义菜单项:

用户界面中的菜单项和操做均存储于数据表中,上面的代码是一个 Odoo 数据文件,描述了要载入 Odoo 数据库的记录。其中的元素是向ir.ui.menu模型写入记录的指示。 id 属性也称做XML ID,用于惟一标识每一个数据元素,以供其它元素引用。例如在添加图书子菜单时,就须要引用顶级菜单的XML ID,即menu_library。XML ID是一个重要话题,将在本系列文章第五篇Odoo 12开发之导入、导出以及模块数据中探讨。

此处添加的菜单项很是简单,仅用到了 name 属性。其它经常使用的属性这里没有使用,没有设置父菜单,由于这是一个顶级菜单。也没有设置 action,因菜单项自己并不作任何事,仅仅用于放置后面要建立的子菜单项。模块还不知道 XML 数据文件的存在,咱们须要在__manifest__.py中使用 data 属性来添加安装或更新时须要加载的模块列表以进行声明。在manifest 文件的字典中加入:

要向Odoo数据库中加载这些菜单设置,须要升级模块。此时还不会有什么显式的效果,因菜单项还不包含可操做子菜单,因此不会显示。在添加好子菜单及合适的访问权限时便可显示。

小贴士:菜单树中的项目仅在含有可见子菜单项时才会显示。底层包含窗口操做视图的菜单项仅当用户拥有该模型访问权限时才可见。

添加权限组

普通用户在使用功能前需得到相应的权限。Odoo 中使用安全组来实现,权限授予组,组中分配用户。Odoo 应用一般有两个组:针对普通用户的用户组,包含额外应用配置权限的管理员组。

下面咱们就来添加这两个安全组。权限安全相关的文件一般放在模块下/security子目录中,这里咱们建立security/library_security.xml 文件来进行权限定义。安全组使用分类来更好地组织关联应用。因此第一步咱们在ir.module.category模型中建立针对图书应用的分类:

下一步,咱们要添加两个安全组,首先添加用户组。在以上结束标签前添加以下 XML 代码块:

记录在res.groups模型中建立,添加了三个字段:

  • name:组名
  • category_id:关联应用,这是一个关联字段,所以使用了 ref 属性来经过 XML ID 链接已建立的分类
  • implied_ids:这是一个one-to-many关联字段,包含一系列组来对组内用户生效。这里使用了一个特殊语法,在本系列文章第五篇Odoo 12开发之导入、导出以及模块数据中会进行介绍。咱们使用了编号4来链接基本内部用户组base.group_user。

而后咱们建立管理员组,授予用户组的全部权限以及为应用管理员保留的其它权限:

像用户组同样,这里也有name, category_id和implied_ids ,implied_ids关联了图书用户组,以继承其权限。还添加了一个 users 字段,让管理员和内部 root 用户自动成为应用管理员。

ℹ️在 Odoo老版本中,admin 管理员用户同时也是 root 用户。Odoo 12中有一个系统 root用户,在用户列表中不显示,仅在框架须要进行提权(sudo)时在内部使用。admin能够登入系统并应拥有全部功能的访问权限,但再也不像系统 root 用户那样能够绕过访问限制。

一样须要在声明文件中添加该 XML 文件:

注意library_security.xml 加在library_menu.xml文件以前,数据文件的加载顺序很是重要,由于咱们只能引用已经定义过的标识符。菜单项常常引用到安全组,因此建议将安全组定义文件放到菜单和视图文件以前。

Odoo 12 开发之建立第一个 Odoo 应用

添加自动化测试

编程的最佳实践包含代码的自动化测试,对于像 Python 这样的动态语言尤其重要,由于它没有编译这一步,只有在解释器实际运行代码时才会报语法错误。好的编辑器可让咱们提早发现问题,但没法像自动化测试这样帮助咱们肯定代码如预期般运行。

Odoo 12中的修改
在老版本中,Odoo 使用YAML文件来进行测试,但 Odoo 12中移除了对YAML文件的支持,因此不能再使用该格式文件。

测试驱动开发(TDD -Test-driven Development) 方法让咱们先写测试,检查错误,而后开发代码直至经过测试。受此方法启示,在添加实际功能前咱们先添加模块测试:

一、测试代码文件名应以test_开头,并经过tests/__init__.py引用。但测试目录(也即 Python 子模块)不该在模块的外层__init__.py中引入,由于仅在测试执行时才会自动查找和加载它。

二、测试应放在tests/子目录中,在tests/__init__.py中添加以下代码:

三、在tests/test_book.py文件中添加实际的测试代码:

以上代码添加一个简单测试用例,建立一本新书并检测active 字段的值是否正确。

四、使用–test-enable参数在安装或升级模块时进行测试

五、Odoo 服务会在升级的模块中查找tests/子目录并运行。如今测试会抛出错误,在输出日志中可看到测试相关的ERROR信息。在为模块添加完图书模型后应该就再也不报错。

测试业务逻辑

如今咱们应为业务逻辑添加测试了,理想状况下每行代码都应有一个测试用例。在tests/test_book.py文件test_create() 方法再加几行代码:

推荐为每一个需检查的操做添加一个测试用例,本条测试与上一条类似,先建立一本新书。由于各个测试用例是相互独立的,用例建立或修改的数据会在测试结束时回滚。而后在建立的记录上调用测试方法来检查所使用 ISBN是否被正确验证。

固然,如今运行测试仍是会失败,由于所测试的功能还未被实现。

测试安全权限

也能够对安全权限进行检测,肯定是否对用户进行了正确的受权。Odoo 中默认测试由不授权限控制的__system__内部用户执行。因此咱们应改变执行测试的用户,来检测是否授予了正确的安全权限。这经过在self.env中修改执行环境来实现,只需把 user 属性修改成但愿运行测试的用户便可。修改tests/test_book.py中的setUp方法以下:

第一条命令调用了父类中的setUp代码,下面一条修改了用于测试的环境self.env为使用 admin 用户的新环境。测试代码的修改到此告一段落。

模型层

既然 Odoo 已经能识别咱们的新模块了,下面就添加一个简单的模型。模型描述业务对象,如商机、销售订单或合做伙伴(用户、供应商等)。模型中有一系列属性,也可定义一些特定业务逻辑。

模型经过 Odoo 模板类派生的 Python 类来实现。它直接与数据库对象对应,Odoo 在安装或升级模块时会自动进行处理。框架中负责这部分的是对象关系映射(ORM -Object Relational Mapping)。

咱们的模块是一个图书管理应用,第一个功能就是管理图书目录,目前这是咱们惟一须要实现的模型。

建立数据模型

Odoo 开发指南中提到模型的 Python 文件应放在models子目录中,每一个模型有一个对应文件。所以咱们在library_app模块主目录下建立models/library_book.py文件。

ℹ️Odoo 官方编码指南请见 Odoo 官网。另外一相关的编码标准文档为 OCA 编码指南

在使用以前,应告知 Python 所需引用的模型目录,仅需在模块主__init__.py文件添加:

要引用所建立的 Python 代码文件,咱们还应添加models/__init__.py文件:

如今咱们能够在models/library_book.py中加入以下内容:

第一行是 Python 代码导入语句,让 Odoo 内核的models和fields对象在这里可用。紧接着声明了新的模型,它是models.Model派生出的一个类。而后_name 属性定义了 Odoo 全局对该模型引用的标识符。注意Python 类名 Book 与框架无关,_name 的值才是模型的标识符。

小贴士:仅有模型名使用点号(.) 来分割关键字,其它如模块、XML 标识符、数据表名等都使用下划线(_)。

注意下面的行都有缩进,对 Python 不熟悉的朋友要知道这很重要:相同缩进表明同一代码块,因此下面的行应采用相同缩进。

_description属性不是必须的,但为模型记录提供了一个用户友好的名称,可用做更好的用户消息。该行以后定义了模型的不一样字段 ,值得一提的是name和active为特殊字段名。默认在其它模型中引用模型时,会使用 name 字段做为记录的标题。

active 字段用于激活记录,默认仅 active 记录会显示。对于日期模型这很是有用,隐藏掉那些用户在平常操做中再也不使用的记录(因历史缘由仍需保留在数据库中)。在本项目中,用于标识图书是否可用。

再来看看其它字段,date_published是一个图书出版日的日期字段,image 是一个存储图书封面的二进制字段。还有一些关联字段:publisher_id是一个出版公司多对一关联,author_ids是做者多对多关联。都是图书与 partner 模型的关联,partner 模型内置于 Odoo 框架中,用户、公司和地址都存储在这里。咱们使用它存储出版商和做者。

字段就是这些,要使代码修改生效,需更新模块来触发数据库中相应对象的建立。菜单中还没法访问这一模型,由于咱们尚未添加。不过能够经过 Technical 菜单来检查新建模型。访问 Settings > Technical > Database Structure > Models(需开启开发者模式),在列表中搜索library.book,而后点击查看模型定义:

Odoo 12 开发之建立第一个 Odoo 应用

如查看一切顺利,说明模型和字段都被正常建立,若是你看不到这些,尝试重启服务升级模型。咱们还能够看到一些未声明的字段,这些是 Odoo 自动为新模型添加的保留字段,这些字段有:

  • id是模型中每条记录的惟一数字标识符
  • create_date和create_uid分别为记录建立时间和建立者
  • display_name为所使用的记录提供文本显示,如其它记录引用它,它就会被计算并默认使用 name 字段中的文本
  • write_date和write_uid分别表示最后修改时间和修改者
  • __last_update是一个助手字段 ,它不存储在数据库,用于作并发检测

设置访问权限

在加载服务时,你可能会注意到输出日志中有一条警告信息:

The model library.book has no access rules, consider adding one.

提示消息已经很明确了,咱们的新模型没有访问规则,因此任何人均可使用。咱们已为应用添加了安全组,如今就为模块受权。

ℹ️在 Odoo 12之前,admin 可自动访问全部数据模型,它是一个不授权限控制的超级用户。在 Odoo 12中则再也不如此,须要在新模型中设置 ACL才对 admin 可见。

添加访问权限控制

要了解须要哪些信息来为模型添加权限,可访问后台Settings > Technical > Security > Access Rights:

Odoo 12 开发之建立第一个 Odoo 应用

这里能够看到一些模型的 ACL(Access Control List),表示容许每一个安全组对记录的操做。这一信息须要经过模块中的数据文件提供,而后载入ir.model.access模型。咱们将为 employee 组添加该模型的全部权限,内部用户是几乎全部人隶属的基本权限组。

ℹ️Odoo 12中的修改
User 表单如今有一个用户类型,仅在开启开发者模式时显示。它容许互斥的几个选项:内部用户,portal门户用户(外部用户如客户)和public公共用户(网站匿名访客)。这一修改用于避免把内部用户放到 portal 或 public 组中一类的错误配置,那样会致使权限的丧失。

权限经过security/ir.model.access.csv文件来实现,添加该文件并加入以下内容:

注:应注意该文件第一行后不要留有空格,不然会致使报错

文件名必须与要载入的模型对应,第一行为列名,CSV 文件中有以下列:

  • id是记录的外部标识符(也称为XML ID),需在模块中惟一
  • name是描述性标题,仅在保证惟一时提供有用信息
  • model_id是赋权模型的外部标识符,模型有ORM自动生成的XML ID,对于library.book,标识符为model_library_book
  • group_id指明受权的安全组,咱们给前文建立的安全组受权:library_group_user和library_group_manager
  • perm_…字段标记read读, write写, create建立, 或unlink删除权限,咱们授予普通用户读权限、管理员全部权限

还应记得在__manifest__.py的 data 属性中添加对新文件的引用,修改后以下:

老规矩升级模块让修改生效,此时警告信息就不见了。咱们经过 admin登陆来检测权限是否正确,admin 属于图书管理员组。

行级权限规则

咱们知道默认 active 标记为 False 的记录不可见,但用户在须要时可以使用过滤器来访问这些记录。假设咱们不但愿普通图书用户访问无效图书,可经过记录规则来实现,即定义过滤器来限制某权限组所能访问的记录。这位于Settings > Technical > Security > Record Rules。

记录规则在ir.rule中定义,和往常同样咱们选择一个惟一名称。还应获取操做的模型及使用权限限制的域过滤器。域过滤器使用 Odoo 中经常使用的元组列表,在第八章 Odoo 12开发之业务逻辑 – 业务流程的支持将讲解域表达式语法。

一般,规则应用于指定安全组,咱们这里应用的是雇员组。若是没有指定的安全组,则应用于全局(global 字段自动设为 True)。全局规则不一样,它们作的限制非全局规则没法重载。

要添加记录规则,需编辑security/library_security.xml文件添加以下代码:

记录规则位于<data noupdate=”1″>元素中,表示这些记录在模型安装时会被建立,但在模型更新时不会被重写。这么作是容许对规则在后面作自定义但避免在执行模型升级时自定义内容丢失。

小贴士:开发过程noupdate=”1″会带来麻烦,由于要修复规则时模块更新不会在数据库中重写数据。因此在开发时能够修改成noupdate=”0″来让数据达到预期结果。

在 groups 字段中,会发现有一个特殊表达式,这是一个带有特殊语法的one-to-many关联字段。元组(4, x)表示x应添加到记录中,此处 x 为一个标记为base.group_user的内部用户组引用。针对多个字段的这种特殊语法在第六章 Odoo 12开发之模型 – 结构化应用数据中探讨。

Odoo 12 开发之建立第一个 Odoo 应用

视图层

视图层为用户界面的描述,视图用 XML 定义,由网页客户端框架生成数据感知的 HTML 视图。可用菜单项开启渲染视图的操做。好比,Users 菜单项处理一个一样名为 Users 的操做,而后渲染一系列视图。有多种可用视图类型,如 list(因历史缘由也称为 tree)列表视图和 form表单视图,以及包含过滤项的右上角搜索框由 search 搜索视图定义。

Odoo 开发指南写到定义用户界面的 XML 文件应放在views/子目录中。接下咱们来建立图书应用的用户界面。下面咱们会逐步改进并更新模块来使更改生效。可使用–dev=all参数来在开发时频繁的升级。使用该参数,视图定义会在 XML 文件中直接读取,无需升级模块便可在 Odoo 中即刻生效。

小贴士:若是因 XML 错误升级失败,没必要惊慌!仔细阅读输出日志的错误信息,就能够找到问题所在。若是以为麻烦,注释掉最近编辑的 XML 版块或删除__manifest__.py中 该XML 文件,从新更新,服务应该就可正确启动了。

添加菜单项

如今有了存储数据的模型,须要添加到用户界面中。首先要作的就是添加相应菜单项。编辑views/library_menu.xml文件,在 XML 元素中定义菜单项以及执行的操做:

用户界面,包括菜单项和操做,存储在数据表中。在安装或升级插件模块时,XML文件会将这些定义载入数据库中的数据文件。以上代码是一个 Odoo 数据文件,表示两条添加到 Odoo 的记录:

  • <act_window>元素定义客户端窗口操做,它按顺序经过启用列表和表单视图打开library.book 模型
  • <menuitem>定义一个调用前面定义的action_library_book操做的顶级菜单项

如今再次升级模块来让修改生效。而后刷新浏览器页面,就能够看到Library顶级菜单,并包含一个子菜单项。点击该菜单会显示一个基本列表视图,记录可经过一个自动生成的表单视图进行编辑。点击 Create 按钮便可查看:

Odoo 12 开发之建立第一个 Odoo 应用

虽然咱们尚未定义用户界面视图,自动生成的列表视图和表单视图也可使用,容许咱们立刻编辑数据。

建立表单视图

全部的视图都存储在数据库ir.ui.view模型中。为模型添加视图,咱们在 XML文件中声明<record>元素来描述视图,在模块安装时 XML 文件会被载入数据库。

添加views/book_view.xml文件来定义表单视图:

这个ir.ui.view记录有三个字段值:name, model和 arch。另外一个重要元素是记录 id,它定义了一个可在其它记录中引用的XML ID标识符。这是library.book 模型的视图,名为Book Form。这个名称仅用于提供信息,无需惟一,但应易于分辨所引用的记录。其实能够彻底省略 name,这种状况下会自动按模型名和视图类型来生成。

最重要的字段是arch,它包含了视图的定义,在 XML 代码中咱们作了高亮显示(博客主题问题没法显示)。<form>标签订义了视图类型并包含视图结构。

此处<form>中包含了要在表单中显示的字段。这些字段会自动使用默认的组件,如 date 字段使用日期选择组件。有时咱们要使用不一样的组件,如以上代码中的author_ids使用了显示标签列表的组件,image字段使用处理图片的相应组件。有关视图元素的详细说明请见第十章 Odoo 12开发以后台视图 – 设计用户界面

不要忘记在声明文件的 data 中加入新建文件,不然咱们的模块将没法识别到并加载该文件:

要使修改载入 Odoo 数据库就须要更新模块。须要从新加载页面来查看修改效果,能够再次点击菜单项或刷新网页(大多数浏览器中快捷键为 F5)。

Odoo 12 开发之建立第一个 Odoo 应用

业务文件表单视图

上面的部分建立了一个基础表单视图,还能够作一些改进。对于文件模型,Odoo 有一个模拟纸张的展现样式,表单包含两个元素:<header>来包含操做按钮和<sheet>来包含数据字段。能够修改上一部分的基础<form>定义为:

 

添加操做按钮

表单可带有执行操做的按钮。这些按钮可用于运行窗口操做,如打开另外一个表单或执行模型中定义的 Python 方法。按钮能够放在表单的任意位置,但对于文件样式表单,推荐的位置是<header>中。

咱们的应用会添加图书 ISBN,和一个用于检测 ISBN 有效性的按钮。代码将放在 Book 模型中,咱们将该方法命名为button_check_isbn()。虽然还未建立该方法,咱们如今能够在表单中先添加相应按钮:

一个按钮的基本属性有:

  • string:定义按钮显示文本
  • type:执行的操做类型
  • name:操做的标识符
  • class:应用 CSS 样式的可选属性,与 HTML 相同

使用组来组织表单

<group>标签可用于组织表单内容。在<group>元素内加<group>会在外层组中建立一个两列布局。推荐在group 元素中添加 name 属性,更易于其它模块对其进行继承。咱们使用该标签来组织内容,修改<sheet>内容以下:

 

完整表单视图

此时library.book的表单视图代码以下:

按钮还没法使用,须要先添加业务逻辑。

Odoo 12 开发之建立第一个 Odoo 应用

添加列表视图和搜索视图

以列表模式显示模型须要使用视图。树状视图能够按层级显示,但大多数状况下仅需显示为普通列表。

能够在book_view.xml文件中添加<tree>视图:

以上定义了一个含有四列的列表:name, author_ids, publisher_id和 date_published。在该列表的右上角,Odoo 显示了一个搜索框。搜索的字段和可用过滤器也由视图定义。一样还在book_view.xml文件中添加:

<field>元素定义在搜索框中输入搜索的字段,这里添加了publisher_id自动提示出版商字段。<filter>元素添加预约义过滤条件,用户经过点击来切换,它使用了特殊的语法,在第十章 Odoo 12开发以后台视图 – 设计用户界面中将会进一步介绍。

ℹ️Odoo 12中的修改
<filter>如今要求包含name=”…”属性,惟一标识每一个过滤器,若是不写,验证会失败,模块将没法安装或升级。

Odoo 12 开发之建立第一个 Odoo 应用

业务逻辑层

业务逻辑层编写应用的业务规则,如验证和自动计算。如今咱们来为按钮添加逻辑,经过在模型 Python 类中编写方法来实现。

添加业务逻辑

上文中咱们在 Book表单中添加了一个按钮,用于检查 ISBN 是否有效。现代 ISBN 包含13位数字,最后一位是由前12位计算所得的检查位。咱们无需深刻到算法的细节,这里是一个实现验证的 Python 方法。应当在class Book(…)中进行添加:

图书模型的button_check_isbn()方法应使用该函数来验证 ISBN 字段中的数字,若是验证失败,应向用户显示警告信息。

首先要导入 Odoo API库,添加对应的 import 及 Odoo Warning异常。这须要编辑library_book.py文件修改前两行为:

而后仍是在models/library_book.py文件Book 类中加入:

对于记录的逻辑,咱们使用@api.multi装饰器。此处 self 表示一个记录集,而后咱们遍历每一条记录。其实@api.multi装饰器能够不写,由于这是模型方法的默认值。这里保留以示清晰。代码遍历全部已选图书,对于每本书,若是 ISBN 有值,则检查有效性,若无值,则向用户抛出一条警告消息。

模型方法无需返回值,但此处需至少返回 True 值。由于不是全部XML-RPC客户端实现都支持None/Null空值,这种状况若返回空值则会致使抛出错误。此时可更新模块并再次运行测试,添加–test-enable参数来肯定测试是否经过。也能够在线测试,进入 Book 表单使用正确和错误的 ISBN点击按钮进行测试。

Odoo 12 开发之建立第一个 Odoo 应用

网页和控制器

Odoo 还提供了一个 web 开发框架,可用于开发与后台应用深度集成的功能。第一步咱们来建立一个显示有效图书列表的简单网页。在请求http://<my-server>/library/books页面时会进行响应,因此/library/books是用于实施的 URL。这里咱们简短地了解下 Odoo 网页开发,这一话题在第十三章 Odoo 12开发之建立网站前端功能中会深刻探讨。

Web控制器是负责渲染网页的组件。控制器是http.Controller中定义的方法,与URL连接(endpoint)绑定。 访问 URL 时执行控制器代码,生成向用户展现的 HTML。咱们使用 QWeb 模板引擎方便HTML的渲染。

按惯例控制器代码放在/controllers子目录中,首先编辑library_app/__init__.py导入控制器模块目录:

而后添加library_app/controllers/__init__.py文件来让目录可被 Python 导入,并在该文件中添加:

接下来就要建立真实的控制器文件library_app/controllers/main.py,并添加以下代码:

这里导入的odoo.http模块,是提供网页相关功能的核心组件。http.Controller是须要继承的类控制器,这里在主控制器类中使用。咱们选择的类名和方法并不关联,@http.route装饰器才是重要的部分,它声明了与类方法关联的 URL 地址,此处为/books。默认访问 URL 地址要求客户登陆,推荐明确指出访问的受权模式,因此这里添加了auth=’user’参数。要容许公开访问,可为@http.route 添加auth=’public’ 参数。

小贴士:若是使用auth=’public’,控制器代码中在进行图书搜索前应使用sudo() 进行提权。这部分在第十三章 Odoo 12开发之建立网站前端功能会进一步讨论。

在这个控制器方法中,咱们使用http.request.env获取环境,使用它可从目录中获取有效图书记录集。最后一步是使用http.request.render() 来处理 library_app.index_template Qweb 模板并生成输出 HTML。可经过字典向模板传值,这里传递了图书记录集。

这时若是重启 Odoo 服务来重载 Python 代码,并访问/library/books会获得一个错误日志:ValueError: External ID not found in the system: library_app.book_list_template。这是由于咱们尚未定义模板。下面就一块儿来定义模板。

QWeb模板是一个视图类型,应放在/views子目录下,咱们来建立views/book_list_template.xml文件:

<template>元素用于声明 QWeb 模板,它事实上是一个存储模块的 base 模型 – ir.ui.view记录的快捷方式。模板中包含要使用的 HTML,并使用 Qweb 的特定属性:t-foreach用于遍历变量 books的每一项,经过控制器的http.request.render()调用来获取;t-field用于渲染记录字段的内容。这里仅简单地使用 QWeb,更多详情见第十三章 Odoo 12开发之建立网站前端功能

在模块的 manifest 中须要声明该 XML 文件来供加载和使用。进行模块升级便可经过http://<my-server>:8069/library/books来访问有效图书的简单列表。

Odoo 12 开发之建立第一个 Odoo 应用

注:以上数据为从 Packt 的 Top 20中添加了当前前3

总结

本文中咱们从0开始建立了一个新模块,了解了模块中经常使用的元素:模型、三个基础视图类型(表单视图、列表视图和搜索视图)、模型方法中的业务逻辑和访问权限。咱们还学习了访问权限控制,包括记录规则以及如何使用网页控制器和 Qweb 模板来建立网页。

在学习过程当中,咱们熟悉了模块开发过程,包含模块升级和应用服务重启来使得修改在 Odoo 中生效。不要忘记在添加模块字段时须要进行更新操做。修改含声明在内的 Python 文件须要重启服务。修改XML或CSV文件需进行更新,一旦不肯定,同时进行重启服务和升级模块操做。

咱们已经学习建立 Odoo 应用的基本元素和步骤,但大多数状况下,咱们的模块都是对已有应用添加功能来进行扩展,咱们将在下一篇文章中一块儿学习。

☞☞☞第四章 Odoo 12 开发之模块继承

学霸专区

  1. library-app是正确的模块名吗?
  2. 模块是否应为其中全部的模型定义访问控制列表(ACL)?
  3. 是否可让某些用户仅访问一个模型记录的子集?
  4. 关联字段和其它字段类型有什么区别?
  5. Odoo 应用中使用的主要视图组件有哪些?
  6. 后台视图如何定义?
  7. Odoo 应用中的业务逻辑应在哪里实现?
  8. Odoo 使用的网页模板引擎是什么?
相关文章
相关标签/搜索