构建ODOO模块
模块构成
一个Odoo模块包含一系列元素:
业务对象
声明为 Python 类,这些资源根据配置信息,由Odoo基础框架自动持久化;
数据文件
XML 或者 CSV 文件,用以声明元数据 MetaData (视图、流程),配置数据 (模块参数化),演示数据等;
Web控制器
处理来自浏览器的请求;
静态资源
网站使用的Images、CSS 或者 javascript等文件;
模块结构
每一个模块都是一个目录,这些目录位于模块目录(module directory) 中。模块目录是通过 --addons-path
选项进行配置的。
提示
大多数的命令行参数都可以通过 配置文件 进行配置。
Odoo 模块由它的 manifest 来声明,参见 manifest documentation 获取更多信息。
一个模块也是一个 Python package, 由 __init__.py
文件声明该模块需要导入的 Python 文件。例如:某个模块的__init__.py
只包含一个mymodule.py
文件。
# __init__.py
from . import mymodule
Odoo 提供了创建模块的机制,doo-bin 有一个子命令:脚手架(scaffold)创建一个空模块:
$ odoo-bin scaffold <module name> <module path to save>
该命令为模块创建了一个子目录,并且自动创建模块需要的标准文件,这些文件大多数只包含一些注释的代码或者一些XML文件,这些文件在后续中会进行详细的讲解。
创建模块练习:1-1
使用上面的命令行工具创建模块 「OpenAcademy」,而且安装到odoo,查看命令执行结果;
- 执行命令 ./odoo-bin scaffold openacademy myaddons
- 修改 manifest 文件,定义模块信息
- 先不要修改其他文件
openacademy/__manifest__.py
openacademy/__init__.py
openacademy/controllers/controllers.py
openacademy/demo/demo.xml
openacademy/models/models.py
openacademy/security/ir.model.access.csv
openacademy/views/templates.xml
对象关系映射
odoo的一个关键组件是 ORM 层,该组件可以避免写 SQL 语句,并且可以提供扩展和安全控制。(注:事实上还是可以写 SQL 但应该尽量避免)
业务对象通过 Python class 定义,通过继承 model ,可以自动实现持久化。
Model可以根据需求定义属性,最重要的一个属性是 _name
,该属性用于 odoo系统识别业务对象。最小化的Model定义如下:
from odoo import models
class MinimalModel(models.Model):
_name = 'test.model'
模型字段-Model Fields
模型字段用于定义和存储对象模型,Fields通过Python class 的attribute定义。
from odoo import models, fields
class LessMinimalModel(models.Model):
_name = 'test.model2'
name = fields.Char()
字段配置属性-Common Attributes
字段可以通过配置属性设置字段的类型、可选等特征。最通用的属性如下:
属性名 | 数据类型 | 缺省值 | 说明 |
---|---|---|---|
string | unicode | field's name | 字段的显示名称(UI Label) |
required | bool | False | 字段是否允许为空 |
help | unicode | '' | 提示信息(UI Tooltip) |
index | bool | False | 是否为该字段创建索引 |
简单字段-Simple Fields
字段有两种广义上的分类方法,“simple“ 和 ”relational“:
- simple:字段值直接存储到模型表中;
- relational:字段链接到本模型或另一个模型;
简单字段的数据类型示例:Date、Boolean、Char
保留字段-Reserved Fields
odoo为模型自动创建一些字段,这些字段是有odoo自动管理的,这些字段不应该被写入值,可以根据需要获取值。
字段名 | 数据类型 | 说明 |
---|---|---|
id | Id | 模型数据的唯一标识 |
create_date | Datetime | 数据创建时间 |
create_uid | Many2one | 数据创建用户 |
write_date | Datetime | 上次修改时间 |
write_uid | Many2one | 上次修改用户 |
特殊字段-Special Fields
缺省情况下,odoo需要一个name
字段,用于显示和搜索等行为,该字段可以通过设置 _rec_name
来重载。
定义模型练习:1-2
在 openacademy 模块下添加一个
Course
业务模型,包括title , description
属性。
数据文件-Data Files
odoo是高度数据驱动的系统(data driven system),虽然通过Python代码开发,但是模块的一些数据还是通过数据文件加载的。
模块数据通过 数据文件声名,数据文件是 XML 格式文件 ,以<record>
元素 定义,每个<record>
创建或更新一条数据库记录。
<odoo>
<data>
<record model="{model name}" id="{record identifier}">
<field name="{a field name}">{a value}</field>
</record>
</data>
</odoo>
model
:odoo数据记录的业务模型名称id
: 外部标识,允许通过该属性值引用该数据记录(而不需要知道在数据库中标识)<field>
:元素包括name
属性,业务模型中字段的名称(例如:code、name、title、description
等),元素内部是该字段的值
数据文件需要在 manifest 文件中声名,用于确定该文件需要被加载。可以在'data'
集合中声名(总是被加载),或者在'demo'
集合中声名(只是在演示模式下加载)。
定义演示数据练习:1-3
编辑
openacademy/demo/demo.xml
文件,添加演示数据
openacademy/demo/demo.xml
操作和菜单-Actions & Menus
操作和菜单是数据库中的常规记录,通常用数据文件定义,操作可以通过三种方式触发:
- 点击菜单项,触发关联的特定操作
- 点击视图中的按钮,触发相关的操作
- 作为对象的上下文操作(Contextual Actions)
菜单定义有些复杂,通过定义一个<menuitem>
菜单项,然后添加到ir.ui.menu
并且关联对应的操作,这种方法相对简单些。
<record model="ir.actions.act_window" id="action_list_ideas">
<field name="name">Ideas</field>
<field name="res_model">idea.idea</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_ideas" parent="menu_root" name="Ideas" sequence="10"
action="action_list_ideas"/>
警告:操作信息必须在菜单信息之前定义。数据文件是顺序执行的,操作的标识必须在数据库中存在,才能被添加到菜单中。
定义菜单练习:1-4
在OpenAcademy的菜单中,添加一个
Courses
的菜单项,以便于用户:
- 显示课程列表
维护课程信息
创建一个
openacademy/views/openacademy.xml
视图文件,并且定义一个操作,用于关联到菜单项将该文件添加到 manifest 文件的 data 集合中
openacademy/__manifest__.py
openacademy/views/openacademy.xml