1. 开发环境搭建
1.1 安装 PostgreSQL 数据库
PostgreSQL 是 Odoo 的数据库管理系统,安装 PostgreSQL 是搭建 Odoo 开发环境的重要一步。以下是安装 PostgreSQL 的详细步骤:
- 下载安装包:访问 PostgreSQL 官方网站 https://www.postgresql.org/download/,选择适合操作系统的版本进行下载。以 Windows 系统为例,推荐下载 PostgreSQL 15.5 版本。
- 安装过程:运行安装程序,按照提示进行操作。在安装过程中,需要设置 PostgreSQL 的管理员用户密码,该用户是
postgres
,类似于 SQL Server 中的sa
用户。 - 创建数据库用户:Odoo 不允许使用超级用户
postgres
连接数据库,因此需要创建一个新的数据库用户odoo
。可以通过以下两种方式创建:- 使用 pgAdmin 4:打开 pgAdmin 4,新建用户,输入用户名
odoo
和密码,然后赋予其superuser
权限,以便该用户可以创建数据库。 - 使用命令行:在命令行中输入以下命令创建用户并赋予其超级用户权限:
create user odoo with password 'odoo'; alter role odoo with superuser;
- 使用 pgAdmin 4:打开 pgAdmin 4,新建用户,输入用户名
1.2 下载 Odoo 17 源码
Odoo 17 的源码是开发的基础,可以从以下两个地址获取:
- GitHub 源码地址:https://github.com/odoo/odoo。这是 Odoo 的官方 GitHub 仓库,但访问时可能需要翻墙。
- Gitee 镜像:https://gitee.com/mirrors/odoo。Gitee 镜像提供了更快的下载速度,推荐从该地址下载 Odoo 17 源码。
1.3 安装依赖和配置
安装依赖和配置是确保 Odoo 17 正常运行的关键环节,具体步骤如下:
- 安装 Miniconda:Miniconda 是一个轻量级的 Python 环境管理工具,可以帮助我们创建和管理虚拟环境。下载地址为 https://docs.conda.io/en/latest/miniconda.html。安装完成后,通过以下命令创建虚拟环境并激活:
conda create -n odoo17 python=3.10 conda activate odoo17
- 安装 Python 依赖:进入 Odoo 17 源码目录,运行以下命令安装
requirements.txt
文件中列出的依赖项:
注意:在安装过程中可能会遇到pip install -r requirements.txt
libsass
库的安装问题,因为它需要 C++ 编译环境。可以先将requirements.txt
文件中libsass
一行注释掉,然后从 https://pypi.org/project/libsass/#files 下载对应平台的编译版本,例如:
再继续运行pip install ./libsass-0.23.0-cp38-abi3-win_amd64.whl
pip install -r requirements.txt
完成剩余依赖的安装。 - 配置 Odoo:创建
odoo.conf
配置文件,内容如下:
该配置文件指定了数据库连接信息、语言、日志级别、管理员密码和 HTTP 端口等参数。[options] addons_path = addons, db_host = 127.0.0.1 db_port = 5432 db_name = odoo17 db_user = odoo db_password = odoo load_language = zh_CN log_level = info admin_passwd = admin http_port = 8069
- 启动 Odoo:在命令行中运行以下命令启动 Odoo 服务器:
如果启动成功,可以通过浏览器访问python odoo-bin -c odoo.conf
http://localhost:8069
来查看 Odoo 的登录页面。# 2. 基础概念理解
2.1 Odoo 架构概览
Odoo 遵循多层架构,具体采用三层架构设计,这种架构将表现层、业务逻辑层和数据存储层分开,具有良好的可扩展性和可维护性。
- 表现层:由 HTML5、JavaScript 和 CSS 组成,负责用户界面的展示和交互。例如,在 Odoo 的销售模块中,用户通过浏览器看到的订单列表、表单等界面元素,都是由表现层代码生成的,为用户提供直观的操作体验。
- 逻辑层:完全用 Python 编写,是 Odoo 的核心部分,负责处理业务逻辑和数据操作。以采购模块为例,当用户创建采购订单时,逻辑层会根据采购规则计算采购金额、检查库存情况等,然后将结果反馈给表现层展示给用户。
- 数据层:仅支持 PostgreSQL 作为关系数据库管理系统(RDBMS)。所有业务数据都存储在 PostgreSQL 数据库中,通过 Odoo 的 ORM(对象关系映射)层,Python 类和数据库表之间可以自动映射,方便开发者进行数据操作。例如,一个客户对象在 Python 中是一个类实例,在数据库中则对应一条客户记录,开发者可以通过 Python 类的方法轻松地对数据库中的客户数据进行增删改查操作。 这种三层架构的设计使得 Odoo 开发可以在不同层进行,开发者可以根据具体需求选择在表现层优化用户界面,或者在逻辑层扩展业务功能,也可以在数据层进行数据优化和管理。
2.2 模块组成与结构
Odoo 的服务器和客户端扩展都以模块的形式存在,模块是 Odoo 开发的基本单元,一个模块可以包含多个元素,用于实现特定的业务功能。
- 业务对象:业务对象是模块的核心,通常被声明为一个 Python 类。这些类中定义的字段会自动映射到数据库列,借助 Odoo 的 ORM 层实现数据的持久化。例如,在一个员工管理模块中,可以定义一个
Employee
类,其中包含name
、age
、position
等字段,这些字段会自动在数据库中生成对应的列,方便存储和管理员工信息。 - 对象视图:用于定义用户界面的显示方式,包括表单视图、列表视图、看板视图等。通过 XML 文件来配置视图的布局和字段展示。以销售订单模块为例,列表视图会显示所有销售订单的基本信息,如订单编号、客户名称、订单金额等;表单视图则可以详细展示每个销售订单的具体内容,包括订单行、交货日期等信息,方便用户进行操作和管理。
- 数据文件:以 XML 或 CSV 格式存在,用于声明模型数据。这些数据文件可以包含视图或报告的定义、配置数据(如模块参数化、安全规则)、演示数据等。例如,在一个新安装的模块中,可以通过数据文件预先定义一些默认的视图和报告,或者设置一些初始的安全规则,方便用户快速开始使用模块。
- 网页控制器:负责处理来自网页浏览器的请求,将用户的操作请求转发到逻辑层进行处理,并将处理结果返回给用户。例如,在一个电子商务模块中,当用户点击购买按钮时,网页控制器会接收这个请求,调用逻辑层的代码处理订单创建、支付等业务逻辑,然后将结果反馈给用户,显示购买成功或失败的页面。
- 静态网页数据:包括图像、CSS 或 JavaScript 文件等,用于增强网页的视觉效果和交互功能。这些文件通常存放在模块的
static
目录下,例如,一个自定义的主题模块可能会包含一些特定的 CSS 文件来改变 Odoo 的界面风格,或者一些 JavaScript 文件来实现一些特殊的交互功能,如动态加载数据、实现拖拽效果等。 一个 Odoo 模块的目录结构通常如下:
module
├── models
│ ├── *.py
│ └── __init__.py
├── views
│ └── *.xml
├── data
│ └── *.xml
├── controllers
│ └── *.py
├── static
│ ├── img
│ ├── css
│ └── js
├── __init__.py
└── __manifest__.py
其中,models
目录存放业务对象的 Python 文件;views
目录存放对象视图的 XML 文件;data
目录存放数据文件;controllers
目录存放网页控制器的 Python 文件;static
目录存放静态网页数据;__init__.py
文件用于初始化模块,将模块中的各个部分导入到 Odoo 系统中;__manifest__.py
文件是模块的清单文件,描述了模块的相关信息,如模块名称、版本、依赖关系等,是模块的重要组成部分。# 3. 创建自定义模块
3.1 搭建模块目录结构
创建自定义模块是 Odoo 开发的重要环节,合理的目录结构有助于模块的组织和维护。以下是搭建模块目录结构的详细步骤:
- 创建模块根目录:在 Odoo 的
addons
目录下创建一个新的文件夹,文件夹的名称即为模块的名称。例如,创建一个名为custom_sales
的模块,其根目录路径为addons/custom_sales
。 - 创建子目录:在模块根目录下创建以下子目录:
- models:用于存放业务对象的 Python 文件,这些文件定义了模块的核心数据结构和业务逻辑。例如,在
custom_sales
模块中,可以创建一个sale_order.py
文件,用于扩展销售订单的业务逻辑。 - views:存放对象视图的 XML 文件,这些文件定义了用户界面的布局和字段展示。例如,创建一个
sale_order_views.xml
文件,用于定义销售订单的表单视图和列表视图。 - data:存放数据文件,如 XML 或 CSV 格式的初始数据、安全规则等。例如,可以在
data
目录下创建一个security.xml
文件,用于定义模块的安全规则。 - controllers:存放网页控制器的 Python 文件,这些文件负责处理来自网页浏览器的请求。例如,创建一个
main.py
文件,用于处理与销售订单相关的网页请求。 - static:存放静态网页数据,如图像、CSS 或 JavaScript 文件。例如,在
static
目录下创建一个css
子目录,存放自定义的 CSS 文件,用于美化销售订单界面。
- models:用于存放业务对象的 Python 文件,这些文件定义了模块的核心数据结构和业务逻辑。例如,在
- 初始化文件:在模块根目录下创建一个
__init__.py
文件,用于初始化模块。该文件的主要作用是将模块中的各个部分导入到 Odoo 系统中,使 Odoo 能够识别和加载该模块。例如,在custom_sales
模块的__init__.py
文件中,可以包含以下内容:
这样,当 Odoo 启动时,会自动加载模块中的from . import models from . import views from . import controllers
models
、views
和controllers
等部分。 - 模块清单文件:在模块根目录下创建一个
__manifest__.py
文件,该文件是模块的清单文件,描述了模块的相关信息,如模块名称、版本、依赖关系等。例如,custom_sales
模块的__manifest__.py
文件内容如下:
该文件指定了模块的名称、版本、分类、描述、依赖模块、数据文件等信息,这些信息对于模块的安装和管理至关重要。{ 'name': 'Custom Sales', 'version': '1.0', 'category': 'Sales', 'summary': 'Customized Sales Module', 'description': """ This module customizes the sales functionality. """, 'depends': ['sale'], # 依赖于 Odoo 的销售模块 'data': [ 'views/sale_order_views.xml', 'data/security.xml', ], 'installable': True, 'application': True, }
通过以上步骤,可以搭建一个完整的 Odoo 自定义模块目录结构,为后续的开发工作奠定基础。
3.2 编写模块元数据文件
模块元数据文件 __manifest__.py
是 Odoo 模块的核心配置文件,它定义了模块的基本信息和行为。以下是编写模块元数据文件的详细步骤:
- 模块名称:指定模块的名称,该名称将显示在 Odoo 的模块列表中。例如:
这里将模块名称设置为'name': 'Custom Sales',
Custom Sales
,用户在 Odoo 的模块管理界面中可以看到这个名称。 - 模块版本:定义模块的版本号,用于标识模块的不同版本。例如:
版本号通常采用主版本号.次版本号的形式,如'version': '1.0',
1.0
。当模块进行更新或修复时,版本号可以相应地进行调整。 - 模块分类:将模块归类到 Odoo 的某个特定类别中,这有助于用户在模块列表中快速找到相关模块。例如:
这里将模块归类到'category': 'Sales',
Sales
类别中,与 Odoo 的销售相关模块放在一起。 - 模块摘要:提供模块的简短描述,通常是一句话,概述模块的主要功能。例如:
这句话将显示在模块的详细信息页面中,帮助用户快速了解模块的核心功能。'summary': 'Customized Sales Module',
- 模块描述:提供模块的详细描述,可以包含多行文本,详细说明模块的功能、特点和使用场景。例如:
这段描述将显示在模块的详细信息页面中,为用户提供更全面的模块信息。'description': """ This module customizes the sales functionality. It includes custom views, reports, and business logic. """,
- 模块依赖:指定模块所依赖的其他 Odoo 模块,这些依赖模块必须先安装,当前模块才能正常运行。例如:
这里指定了模块依赖于 Odoo 的'depends': ['sale'],
sale
模块,这意味着在安装custom_sales
模块之前,必须先安装sale
模块。 - 模块数据文件:列出模块中包含的数据文件,这些文件可以是 XML 或 CSV 格式,用于定义视图、报告、安全规则等。例如:
这里列出了模块中的两个数据文件:'data': [ 'views/sale_order_views.xml', 'data/security.xml', ],
sale_order_views.xml
和security.xml
。Odoo 在安装模块时会自动加载这些文件。 - 模块可安装性:指定模块是否可安装。如果设置为
True
,则模块可以在 Odoo 中安装;如果设置为False
,则模块将被隐藏,无法安装。例如:
这里将模块设置为可安装。'installable': True,
- 模块是否为应用程序:指定模块是否为一个独立的应用程序。如果设置为
True
,则模块将在 Odoo 的应用程序菜单中显示;如果设置为False
,则模块不会显示在应用程序菜单中。例如:
这里将模块设置为一个独立的应用程序,用户可以在 Odoo 的应用程序菜单中找到并使用它。'application': True,
通过以上步骤,可以编写一个完整的模块元数据文件 __manifest__.py
,为 Odoo 模块的安装和管理提供必要的信息。# 4. 定义模型与字段
4.1 创建模型类
在 Odoo 中,模型是业务对象的核心,用于定义数据结构和业务逻辑。创建模型类是开发自定义模块的关键步骤之一。以下是创建模型类的具体方法和注意事项:
- 模型类的定义位置:模型类通常定义在模块的
models
目录下的 Python 文件中。例如,在custom_sales
模块中,可以在models
目录下创建一个sale_order.py
文件来定义销售订单的模型类。 - 模型类的基本结构:模型类继承自
odoo.models.Model
类,通过定义类属性和方法来实现数据结构和业务逻辑。例如,定义一个简单的销售订单模型类:
其中,from odoo import models, fields class CustomSaleOrder(models.Model): _name = 'custom.sale.order' _description = 'Custom Sale Order'
_name
是模型的唯一标识,通常以模块名加点加模型名的形式表示,如custom.sale.order
;_description
是模型的描述,用于在 Odoo 界面中显示模型的名称。 - 模型类的初始化:在模块的
__init__.py
文件中导入模型类,以便 Odoo 能够识别和加载该模型。例如,在custom_sales
模块的__init__.py
文件中添加以下内容:
然后在from . import models
models/__init__.py
文件中导入具体的模型类:
这样,当 Odoo 启动时,会自动加载from . import sale_order
CustomSaleOrder
模型类。
4.2 添加字段类型
字段是模型类中用于存储数据的基本单元,Odoo 提供了多种字段类型来满足不同的业务需求。以下是常见的字段类型及其使用方法:
- Char 字段:用于存储短文本,如名称、代码等。例如,在销售订单模型中添加一个订单编号字段:
其中,order_number = fields.Char(string='Order Number', required=True)
string
参数是字段的显示名称,required
参数表示该字段是必填的。 - Integer 字段:用于存储整数。例如,添加一个订单数量字段:
order_quantity = fields.Integer(string='Order Quantity')
- Float 字段:用于存储浮点数,常用于金额、价格等。例如,添加一个订单金额字段:
其中,order_amount = fields.Float(string='Order Amount', digits=(10, 2))
digits
参数用于指定浮点数的精度,如(10, 2)
表示最多 10 位数字,其中小数部分占 2 位。 - Boolean 字段:用于存储布尔值,表示是/否的状态。例如,添加一个是否已发货字段:
其中,is_shipped = fields.Boolean(string='Is Shipped', default=False)
default
参数用于指定字段的默认值。 - Date 和 Datetime 字段:分别用于存储日期和日期时间。例如,添加一个订单日期字段:
其中,order_date = fields.Date(string='Order Date', default=fields.Date.today)
default
参数使用fields.Date.today
方法为字段设置默认值为当前日期。 - Selection 字段:用于存储一组预定义的选项。例如,添加一个订单状态字段:
其中,选项以元组列表的形式定义,每个元组的第一个元素是选项的值,第二个元素是选项的显示名称。order_status = fields.Selection([ ('draft', 'Draft'), ('confirmed', 'Confirmed'), ('shipped', 'Shipped'), ('done', 'Done') ], string='Order Status', default='draft')
- Many2one 字段:用于建立模型之间的关联关系,表示多对一的关系。例如,销售订单关联到客户模型:
其中,customer_id = fields.Many2one('res.partner', string='Customer')
res.partner
是 Odoo 中客户模型的名称,customer_id
字段将销售订单与客户模型关联起来,可以通过该字段访问客户的相关信息。 - One2many 字段:用于表示一对多的关系,通常与 Many2one 字段配合使用。例如,在客户模型中添加一个字段来关联其所有的销售订单:
这样,客户模型可以通过sale_order_ids = fields.One2many('custom.sale.order', 'customer_id', string='Sales Orders')
sale_order_ids
字段访问其所有的销售订单记录。 - Many2many 字段:用于表示多对多的关系。例如,销售订单与产品之间的多对多关系:
其中,product_ids = fields.Many2many('product.product', string='Products')
product.product
是 Odoo 中产品模型的名称,product_ids
字段表示销售订单与多个产品之间的关联关系。
通过合理地定义模型类和添加字段,可以构建出满足业务需求的数据结构,为 Odoo 模块的开发奠定坚实的基础。# 5. 视图与用户界面
5.1 创建列表视图
在 Odoo 中,列表视图用于以表格形式展示数据,是用户界面的重要组成部分。以下是创建列表视图的详细步骤和注意事项:
定义视图文件:列表视图通常定义在模块的
views
目录下的 XML 文件中。例如,在custom_sales
模块中,可以在views
目录下创建一个sale_order_views.xml
文件来定义销售订单的列表视图。视图的基本结构:列表视图通过
<tree>
标签定义,其中可以包含多个<field>
标签来指定要显示的字段。例如,定义一个简单的销售订单列表视图:<record id="view_sale_order_tree" model="ir.ui.view"> <field name="name">custom.sale.order.tree</field> <field name="model">custom.sale.order</field> <field name="arch" type="xml"> <tree string="Sales Orders"> <field name="order_number"/> <field name="customer_id"/> <field name="order_date"/> <field name="order_amount"/> <field name="order_status"/> </tree> </field> </record>
id
:视图的唯一标识,用于在 Odoo 系统中引用该视图。model
:指定该视图对应的模型名称,这里是custom.sale.order
。<tree>
标签:定义列表视图的结构,string
属性是视图的标题。<field>
标签:指定要显示的字段,字段名称必须与模型中定义的字段名称一致。
字段排序与显示:可以通过
<field>
标签的sequence
属性来控制字段的显示顺序。例如:<field name="order_number" sequence="1"/> <field name="customer_id" sequence="2"/>
数字越小,字段越靠前。
字段显示格式:对于某些字段,可以指定显示格式。例如,对于日期字段,可以通过
options
属性设置显示格式:<field name="order_date" options="{'format': 'dd/mm/yyyy'}"/>
添加操作按钮:可以在列表视图中添加操作按钮,例如添加一个“确认订单”按钮:
<tree string="Sales Orders"> <field name="order_number"/> <field name="customer_id"/> <field name="order_date"/> <field name="order_amount"/> <field name="order_status"/> <button name="action_confirm" string="Confirm" type="object" class="oe_highlight"/> </tree>
name
:按钮调用的方法名称,必须在模型中定义。string
:按钮的显示文本。type
:按钮的类型,object
表示调用模型中的方法。class
:按钮的样式类,oe_highlight
用于突出显示按钮。
5.2 设计表单视图
表单视图用于展示和编辑单个记录的详细信息,是用户界面中另一个重要的视图类型。以下是设计表单视图的详细步骤和注意事项:
定义表单视图文件:表单视图同样定义在模块的
views
目录下的 XML 文件中。例如,在custom_sales
模块的sale_order_views.xml
文件中定义销售订单的表单视图。视图的基本结构:表单视图通过
<form>
标签定义,其中可以包含多个<group>
、<field>
、<button>
等标签来组织和显示字段。例如:<record id="view_sale_order_form" model="ir.ui.view"> <field name="name">custom.sale.order.form</field> <field name="model">custom.sale.order</field> <field name="arch" type="xml"> <form string="Sale Order"> <sheet> <group> <field name="order_number"/> <field name="customer_id"/> <field name="order_date"/> </group> <group> <field name="order_amount"/> <field name="order_status"/> </group> </sheet> <footer> <button name="action_confirm" string="Confirm" type="object" class="oe_highlight"/> <button string="Cancel" special="cancel"/> </footer> </form> </field> </record>
id
:视图的唯一标识。model
:指定该视图对应的模型名称。<form>
标签:定义表单视图的结构,string
属性是视图的标题。<sheet>
标签:用于组织表单内容,使其更具可读性。<group>
标签:用于分组显示字段,方便用户查看和编辑。<field>
标签:指定要显示的字段。<footer>
标签:用于放置操作按钮,如“确认”和“取消”按钮。
字段显示方式:可以通过
<field>
标签的widget
属性来指定字段的显示方式。例如,对于文本字段,可以使用textarea
小部件:<field name="description" widget="textarea"/>
字段默认值:可以通过
<field>
标签的default
属性为字段设置默认值。例如:<field name="order_status" default="draft"/>
字段只读模式:可以通过
<field>
标签的readonly
属性设置字段在某些情况下为只读。例如:<field name="order_number" readonly="1"/>
关联字段的显示:对于 Many2one 字段,可以通过
<field>
标签的domain
属性来限制可选择的记录。例如:<field name="customer_id" domain="[('is_customer', '=', True)]"/>
通过以上步骤,可以创建和设计出满足业务需求的列表视图和表单视图,为用户提供直观且易于操作的用户界面。# 6. 安全与权限设置
6.1 定义访问控制规则
在 Odoo 中,访问控制规则是确保数据安全和用户权限管理的关键机制。通过定义访问控制规则,可以精确地控制用户对数据的访问权限,包括读、写、创建和删除等操作。以下是定义访问控制规则的详细步骤和注意事项:
访问控制规则文件:访问控制规则通常定义在模块的
data
目录下的 XML 文件中。例如,在custom_sales
模块中,可以在data
目录下创建一个security.xml
文件来定义访问控制规则。规则的基本结构:访问控制规则通过
<record>
标签定义,其中包含<field>
标签来指定规则的详细信息。例如,定义一个简单的访问控制规则:<record id="rule_sale_order_read" model="ir.rule"> <field name="name">Sale Order Read Access</field> <field name="model_id" ref="model_custom_sale_order"/> <field name="domain_force">[('order_status', '=', 'done')]</field> <field name="perm_read" eval="1"/> <field name="perm_write" eval="0"/> <field name="perm_create" eval="0"/> <field name="perm_delete" eval="0"/> <field name="groups" eval="[(4, ref('group_sales_manager'))]"/> </record>
id
:规则的唯一标识,用于在 Odoo 系统中引用该规则。model
:指定该规则对应的模型名称,这里是ir.rule
。name
:规则的名称,用于在 Odoo 界面中显示。model_id
:指定规则所应用的模型,通过ref
引用模型的外部标识符。domain_force
:定义规则的过滤条件,只有满足该条件的记录才会受到该规则的约束。例如,[('order_status', '=', 'done')]
表示该规则只对订单状态为done
的记录生效。perm_read
、perm_write
、perm_create
、perm_delete
:分别表示读、写、创建和删除权限,eval="1"
表示允许,eval="0"
表示禁止。groups
:指定该规则适用的用户组,通过ref
引用用户组的外部标识符。
规则的作用范围:访问控制规则可以全局生效,也可以仅对特定用户组生效。通过在
groups
字段中指定用户组,可以实现对不同用户组的差异化权限管理。例如,上述规则仅对销售经理组(group_sales_manager
)生效。规则的优先级:当多个规则同时适用时,Odoo 会根据规则的定义顺序和优先级进行综合判断。默认情况下,规则的优先级由其定义顺序决定,先定义的规则优先级更高。如果需要调整规则的优先级,可以通过
sequence
属性进行设置。
通过合理地定义访问控制规则,可以确保用户只能访问和操作其权限范围内的数据,从而提高系统的安全性和数据的完整性。
6.2 创建用户组
用户组是 Odoo 中用于管理用户权限的重要工具,通过创建用户组并分配不同的权限,可以实现对用户的精细化管理。以下是创建用户组的详细步骤和注意事项:
用户组文件:用户组通常定义在模块的
data
目录下的 XML 文件中。例如,在custom_sales
模块中,可以在data
目录下创建一个security.xml
文件来定义用户组。用户组的基本结构:用户组通过
<record>
标签定义,其中包含<field>
标签来指定用户组的详细信息。例如,定义一个销售经理用户组:<record id="group_sales_manager" model="res.groups"> <field name="name">Sales Manager</field> <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/> </record>
id
:用户组的唯一标识,用于在 Odoo 系统中引用该用户组。model
:指定该用户组对应的模型名称,这里是res.groups
。name
:用户组的名称,用于在 Odoo 界面中显示。implied_ids
:指定该用户组所包含的其他用户组,通过ref
引用其他用户组的外部标识符。例如,base.group_user
是 Odoo 默认的用户组,表示普通用户组。
用户组的权限分配:用户组的权限通过访问控制规则进行分配。在定义访问控制规则时,通过
groups
字段指定该规则适用的用户组,从而实现对用户组的权限管理。例如,上述访问控制规则仅对销售经理组(group_sales_manager
)生效,这意味着销售经理组的用户将获得相应的权限。用户组的层级关系:用户组之间可以存在层级关系,一个用户组可以包含多个子用户组。通过在
implied_ids
字段中指定子用户组,可以实现用户组的层级结构。例如,定义一个销售员用户组,并将其包含在销售经理组中:<record id="group_sales_user" model="res.groups"> <field name="name">Sales User</field> <field name="implied_ids" eval="[(4, ref('group_sales_manager'))]"/> </record>
这样,销售员用户组的用户将自动继承销售经理组的权限。
用户组的使用场景:用户组可以用于多种场景,例如:
- 模块访问权限:通过用户组控制用户对特定模块的访问权限。例如,只有销售经理组的用户才能访问销售模块。
- 数据访问权限:通过用户组结合访问控制规则,控制用户对特定数据的访问权限。例如,只有销售经理组的用户才能查看已完成的销售订单。
- 功能权限:通过用户组控制用户对特定功能的使用权限。例如,只有销售经理组的用户才能创建新的销售订单。
通过创建合理的用户组并分配适当的权限,可以实现对用户的精细化管理,确保系统的安全性和数据的完整性,同时提高用户的操作效率和用户体验。# 7. 测试与调试
7.1 启动 Odoo 服务
启动 Odoo 服务是测试模块功能的第一步,确保开发环境正常运行。在命令行中运行以下命令启动 Odoo 服务器:
python odoo-bin -c odoo.conf
如果启动成功,可以通过浏览器访问 http://localhost:8069
来查看 Odoo 的登录页面。在启动过程中,需要确保以下几点:
- 配置文件正确:
odoo.conf
配置文件中指定的数据库连接信息、语言、日志级别、管理员密码和 HTTP 端口等参数必须正确无误。 - 依赖环境完整:确保所有 Python 依赖已正确安装,包括
libsass
等可能需要额外编译的库。 - 数据库可用:确保 PostgreSQL 数据库已正确安装,并且创建了对应的数据库用户和数据库。
启动过程中可能会遇到的问题及解决方法:
- 端口冲突:如果
http_port
指定的端口被其他应用占用,可以修改配置文件中的端口号,例如改为8070
。 - 依赖缺失:如果某些依赖未正确安装,可能会导致启动失败。可以通过运行
pip install -r requirements.txt
来重新安装依赖。 - 数据库连接失败:检查数据库用户密码是否正确,以及数据库服务是否已启动。
7.2 测试模块功能
测试模块功能是确保开发的模块能够正常运行并满足业务需求的关键步骤。以下是测试模块功能的具体方法和注意事项:
功能测试
- 用户界面测试:登录 Odoo 系统,进入模块的应用程序,检查用户界面是否正常显示。例如,检查自定义模块的列表视图和表单视图是否正确加载,字段是否显示正常。
- 数据操作测试:测试数据的增删改查功能是否正常。例如,在销售订单模块中,创建一个新的销售订单,检查是否可以成功保存;修改已存在的销售订单,检查修改后的数据是否正确保存;删除销售订单,检查是否能够成功删除。
- 关联关系测试:如果模块中定义了模型之间的关联关系,例如 Many2one、One2many 或 Many2many 字段,需要测试这些关联关系是否正常工作。例如,检查销售订单是否能够正确关联到客户模型,以及客户模型是否能够正确显示其所有的销售订单。
权限测试
- 访问控制规则测试:根据定义的访问控制规则,测试不同用户组的权限是否正确。例如,对于销售经理组,检查是否能够读取已完成的销售订单,而对于普通用户组,检查是否无法读取这些订单。
- 用户组权限测试:测试用户组的权限分配是否正确。例如,检查销售员用户组是否能够创建新的销售订单,但无法删除订单。
性能测试
- 加载时间测试:测试模块的加载时间是否合理。例如,检查销售订单列表视图的加载时间是否在可接受范围内,如果加载时间过长,可能需要优化查询语句或数据库索引。
- 并发测试:如果模块需要支持高并发操作,可以使用工具进行并发测试,检查系统在高并发情况下的性能表现。
日志与错误处理
- 日志查看:查看 Odoo 的日志文件,检查是否有错误信息或警告信息。日志文件通常位于配置文件中指定的日志路径,例如
log_level = info
时,日志文件会记录详细的信息。 - 错误处理:如果在测试过程中遇到错误,需要根据错误信息进行排查和修复。常见的错误包括数据库查询错误、Python 代码错误等。
通过以上测试步骤,可以全面验证自定义模块的功能是否正常,确保模块能够满足业务需求并稳定运行。
1. 开发环境搭建
1.1 安装 PostgreSQL 数据库
PostgreSQL 是 Odoo 的数据库管理系统,安装 PostgreSQL 是搭建 Odoo 开发环境的重要一步。以下是安装 PostgreSQL 的详细步骤:
- 下载安装包:访问 PostgreSQL 官方网站 https://www.postgresql.org/download/,选择适合操作系统的版本进行下载。以 Windows 系统为例,推荐下载 PostgreSQL 15.5 版本。
- 安装过程:运行安装程序,按照提示进行操作。在安装过程中,需要设置 PostgreSQL 的管理员用户密码,该用户是
postgres
,类似于 SQL Server 中的sa
用户。 - 创建数据库用户:Odoo 不允许使用超级用户
postgres
连接数据库,因此需要创建一个新的数据库用户odoo
。可以通过以下两种方式创建:- 使用 pgAdmin 4:打开 pgAdmin 4,新建用户,输入用户名
odoo
和密码,然后赋予其superuser
权限,以便该用户可以创建数据库。 - 使用命令行:在命令行中输入以下命令创建用户并赋予其超级用户权限:
create user odoo with password 'odoo'; alter role odoo with superuser;
- 使用 pgAdmin 4:打开 pgAdmin 4,新建用户,输入用户名
1.2 下载 Odoo 17 源码
Odoo 17 的源码是开发的基础,可以从以下两个地址获取:
- GitHub 源码地址:https://github.com/odoo/odoo。这是 Odoo 的官方 GitHub 仓库,但访问时可能需要翻墙。
- Gitee 镜像:https://gitee.com/mirrors/odoo。Gitee 镜像提供了更快的下载速度,推荐从该地址下载 Odoo 17 源码。
1.3 安装依赖和配置
安装依赖和配置是确保 Odoo 17 正常运行的关键环节,具体步骤如下:
- 安装 Miniconda:Miniconda 是一个轻量级的 Python 环境管理工具,可以帮助我们创建和管理虚拟环境。下载地址为 https://docs.conda.io/en/latest/miniconda.html。安装完成后,通过以下命令创建虚拟环境并激活:
conda create -n odoo17 python=3.10 conda activate odoo17
- 安装 Python 依赖:进入 Odoo 17 源码目录,运行以下命令安装
requirements.txt
文件中列出的依赖项:
注意:在安装过程中可能会遇到pip install -r requirements.txt
libsass
库的安装问题,因为它需要 C++ 编译环境。可以先将requirements.txt
文件中libsass
一行注释掉,然后从 https://pypi.org/project/libsass/#files 下载对应平台的编译版本,例如:
再继续运行pip install ./libsass-0.23.0-cp38-abi3-win_amd64.whl
pip install -r requirements.txt
完成剩余依赖的安装。 - 配置 Odoo:创建
odoo.conf
配置文件,内容如下:
该配置文件指定了数据库连接信息、语言、日志级别、管理员密码和 HTTP 端口等参数。[options] addons_path = addons, db_host = 127.0.0.1 db_port = 5432 db_name = odoo17 db_user = odoo db_password = odoo load_language = zh_CN log_level = info admin_passwd = admin http_port = 8069
- 启动 Odoo:在命令行中运行以下命令启动 Odoo 服务器:
如果启动成功,可以通过浏览器访问python odoo-bin -c odoo.conf
http://localhost:8069
来查看 Odoo 的登录页面。# 2. 基础概念理解
2.1 Odoo 架构概览
Odoo 遵循多层架构,具体采用三层架构设计,这种架构将表现层、业务逻辑层和数据存储层分开,具有良好的可扩展性和可维护性。
- 表现层:由 HTML5、JavaScript 和 CSS 组成,负责用户界面的展示和交互。例如,在 Odoo 的销售模块中,用户通过浏览器看到的订单列表、表单等界面元素,都是由表现层代码生成的,为用户提供直观的操作体验。
- 逻辑层:完全用 Python 编写,是 Odoo 的核心部分,负责处理业务逻辑和数据操作。以采购模块为例,当用户创建采购订单时,逻辑层会根据采购规则计算采购金额、检查库存情况等,然后将结果反馈给表现层展示给用户。
- 数据层:仅支持 PostgreSQL 作为关系数据库管理系统(RDBMS)。所有业务数据都存储在 PostgreSQL 数据库中,通过 Odoo 的 ORM(对象关系映射)层,Python 类和数据库表之间可以自动映射,方便开发者进行数据操作。例如,一个客户对象在 Python 中是一个类实例,在数据库中则对应一条客户记录,开发者可以通过 Python 类的方法轻松地对数据库中的客户数据进行增删改查操作。 这种三层架构的设计使得 Odoo 开发可以在不同层进行,开发者可以根据具体需求选择在表现层优化用户界面,或者在逻辑层扩展业务功能,也可以在数据层进行数据优化和管理。
2.2 模块组成与结构
Odoo 的服务器和客户端扩展都以模块的形式存在,模块是 Odoo 开发的基本单元,一个模块可以包含多个元素,用于实现特定的业务功能。
- 业务对象:业务对象是模块的核心,通常被声明为一个 Python 类。这些类中定义的字段会自动映射到数据库列,借助 Odoo 的 ORM 层实现数据的持久化。例如,在一个员工管理模块中,可以定义一个
Employee
类,其中包含name
、age
、position
等字段,这些字段会自动在数据库中生成对应的列,方便存储和管理员工信息。 - 对象视图:用于定义用户界面的显示方式,包括表单视图、列表视图、看板视图等。通过 XML 文件来配置视图的布局和字段展示。以销售订单模块为例,列表视图会显示所有销售订单的基本信息,如订单编号、客户名称、订单金额等;表单视图则可以详细展示每个销售订单的具体内容,包括订单行、交货日期等信息,方便用户进行操作和管理。
- 数据文件:以 XML 或 CSV 格式存在,用于声明模型数据。这些数据文件可以包含视图或报告的定义、配置数据(如模块参数化、安全规则)、演示数据等。例如,在一个新安装的模块中,可以通过数据文件预先定义一些默认的视图和报告,或者设置一些初始的安全规则,方便用户快速开始使用模块。
- 网页控制器:负责处理来自网页浏览器的请求,将用户的操作请求转发到逻辑层进行处理,并将处理结果返回给用户。例如,在一个电子商务模块中,当用户点击购买按钮时,网页控制器会接收这个请求,调用逻辑层的代码处理订单创建、支付等业务逻辑,然后将结果反馈给用户,显示购买成功或失败的页面。
- 静态网页数据:包括图像、CSS 或 JavaScript 文件等,用于增强网页的视觉效果和交互功能。这些文件通常存放在模块的
static
目录下,例如,一个自定义的主题模块可能会包含一些特定的 CSS 文件来改变 Odoo 的界面风格,或者一些 JavaScript 文件来实现一些特殊的交互功能,如动态加载数据、实现拖拽效果等。 一个 Odoo 模块的目录结构通常如下:
module
├── models
│ ├── *.py
│ └── __init__.py
├── views
│ └── *.xml
├── data
│ └── *.xml
├── controllers
│ └── *.py
├── static
│ ├── img
│ ├── css
│ └── js
├── __init__.py
└── __manifest__.py
其中,models
目录存放业务对象的 Python 文件;views
目录存放对象视图的 XML 文件;data
目录存放数据文件;controllers
目录存放网页控制器的 Python 文件;static
目录存放静态网页数据;__init__.py
文件用于初始化模块,将模块中的各个部分导入到 Odoo 系统中;__manifest__.py
文件是模块的清单文件,描述了模块的相关信息,如模块名称、版本、依赖关系等,是模块的重要组成部分。# 3. 创建自定义模块
3.1 搭建模块目录结构
创建自定义模块是 Odoo 开发的重要环节,合理的目录结构有助于模块的组织和维护。以下是搭建模块目录结构的详细步骤:
- 创建模块根目录:在 Odoo 的
addons
目录下创建一个新的文件夹,文件夹的名称即为模块的名称。例如,创建一个名为custom_sales
的模块,其根目录路径为addons/custom_sales
。 - 创建子目录:在模块根目录下创建以下子目录:
- models:用于存放业务对象的 Python 文件,这些文件定义了模块的核心数据结构和业务逻辑。例如,在
custom_sales
模块中,可以创建一个sale_order.py
文件,用于扩展销售订单的业务逻辑。 - views:存放对象视图的 XML 文件,这些文件定义了用户界面的布局和字段展示。例如,创建一个
sale_order_views.xml
文件,用于定义销售订单的表单视图和列表视图。 - data:存放数据文件,如 XML 或 CSV 格式的初始数据、安全规则等。例如,可以在
data
目录下创建一个security.xml
文件,用于定义模块的安全规则。 - controllers:存放网页控制器的 Python 文件,这些文件负责处理来自网页浏览器的请求。例如,创建一个
main.py
文件,用于处理与销售订单相关的网页请求。 - static:存放静态网页数据,如图像、CSS 或 JavaScript 文件。例如,在
static
目录下创建一个css
子目录,存放自定义的 CSS 文件,用于美化销售订单界面。
- models:用于存放业务对象的 Python 文件,这些文件定义了模块的核心数据结构和业务逻辑。例如,在
- 初始化文件:在模块根目录下创建一个
__init__.py
文件,用于初始化模块。该文件的主要作用是将模块中的各个部分导入到 Odoo 系统中,使 Odoo 能够识别和加载该模块。例如,在custom_sales
模块的__init__.py
文件中,可以包含以下内容:
这样,当 Odoo 启动时,会自动加载模块中的from . import models from . import views from . import controllers
models
、views
和controllers
等部分。 - 模块清单文件:在模块根目录下创建一个
__manifest__.py
文件,该文件是模块的清单文件,描述了模块的相关信息,如模块名称、版本、依赖关系等。例如,custom_sales
模块的__manifest__.py
文件内容如下:
该文件指定了模块的名称、版本、分类、描述、依赖模块、数据文件等信息,这些信息对于模块的安装和管理至关重要。{ 'name': 'Custom Sales', 'version': '1.0', 'category': 'Sales', 'summary': 'Customized Sales Module', 'description': """ This module customizes the sales functionality. """, 'depends': ['sale'], # 依赖于 Odoo 的销售模块 'data': [ 'views/sale_order_views.xml', 'data/security.xml', ], 'installable': True, 'application': True, }
通过以上步骤,可以搭建一个完整的 Odoo 自定义模块目录结构,为后续的开发工作奠定基础。
3.2 编写模块元数据文件
模块元数据文件 __manifest__.py
是 Odoo 模块的核心配置文件,它定义了模块的基本信息和行为。以下是编写模块元数据文件的详细步骤:
- 模块名称:指定模块的名称,该名称将显示在 Odoo 的模块列表中。例如:
这里将模块名称设置为'name': 'Custom Sales',
Custom Sales
,用户在 Odoo 的模块管理界面中可以看到这个名称。 - 模块版本:定义模块的版本号,用于标识模块的不同版本。例如:
版本号通常采用主版本号.次版本号的形式,如'version': '1.0',
1.0
。当模块进行更新或修复时,版本号可以相应地进行调整。 - 模块分类:将模块归类到 Odoo 的某个特定类别中,这有助于用户在模块列表中快速找到相关模块。例如:
这里将模块归类到'category': 'Sales',
Sales
类别中,与 Odoo 的销售相关模块放在一起。 - 模块摘要:提供模块的简短描述,通常是一句话,概述模块的主要功能。例如:
这句话将显示在模块的详细信息页面中,帮助用户快速了解模块的核心功能。'summary': 'Customized Sales Module',
- 模块描述:提供模块的详细描述,可以包含多行文本,详细说明模块的功能、特点和使用场景。例如:
这段描述将显示在模块的详细信息页面中,为用户提供更全面的模块信息。'description': """ This module customizes the sales functionality. It includes custom views, reports, and business logic. """,
- 模块依赖:指定模块所依赖的其他 Odoo 模块,这些依赖模块必须先安装,当前模块才能正常运行。例如:
这里指定了模块依赖于 Odoo 的'depends': ['sale'],
sale
模块,这意味着在安装custom_sales
模块之前,必须先安装sale
模块。 - 模块数据文件:列出模块中包含的数据文件,这些文件可以是 XML 或 CSV 格式,用于定义视图、报告、安全规则等。例如:
这里列出了模块中的两个数据文件:'data': [ 'views/sale_order_views.xml', 'data/security.xml', ],
sale_order_views.xml
和security.xml
。Odoo 在安装模块时会自动加载这些文件。 - 模块可安装性:指定模块是否可安装。如果设置为
True
,则模块可以在 Odoo 中安装;如果设置为False
,则模块将被隐藏,无法安装。例如:
这里将模块设置为可安装。'installable': True,
- 模块是否为应用程序:指定模块是否为一个独立的应用程序。如果设置为
True
,则模块将在 Odoo 的应用程序菜单中显示;如果设置为False
,则模块不会显示在应用程序菜单中。例如:
这里将模块设置为一个独立的应用程序,用户可以在 Odoo 的应用程序菜单中找到并使用它。'application': True,
通过以上步骤,可以编写一个完整的模块元数据文件 __manifest__.py
,为 Odoo 模块的安装和管理提供必要的信息。# 4. 定义模型与字段
4.1 创建模型类
在 Odoo 中,模型是业务对象的核心,用于定义数据结构和业务逻辑。创建模型类是开发自定义模块的关键步骤之一。以下是创建模型类的具体方法和注意事项:
- 模型类的定义位置:模型类通常定义在模块的
models
目录下的 Python 文件中。例如,在custom_sales
模块中,可以在models
目录下创建一个sale_order.py
文件来定义销售订单的模型类。 - 模型类的基本结构:模型类继承自
odoo.models.Model
类,通过定义类属性和方法来实现数据结构和业务逻辑。例如,定义一个简单的销售订单模型类:
其中,from odoo import models, fields class CustomSaleOrder(models.Model): _name = 'custom.sale.order' _description = 'Custom Sale Order'
_name
是模型的唯一标识,通常以模块名加点加模型名的形式表示,如custom.sale.order
;_description
是模型的描述,用于在 Odoo 界面中显示模型的名称。 - 模型类的初始化:在模块的
__init__.py
文件中导入模型类,以便 Odoo 能够识别和加载该模型。例如,在custom_sales
模块的__init__.py
文件中添加以下内容:
然后在from . import models
models/__init__.py
文件中导入具体的模型类:
这样,当 Odoo 启动时,会自动加载from . import sale_order
CustomSaleOrder
模型类。
4.2 添加字段类型
字段是模型类中用于存储数据的基本单元,Odoo 提供了多种字段类型来满足不同的业务需求。以下是常见的字段类型及其使用方法:
- Char 字段:用于存储短文本,如名称、代码等。例如,在销售订单模型中添加一个订单编号字段:
其中,order_number = fields.Char(string='Order Number', required=True)
string
参数是字段的显示名称,required
参数表示该字段是必填的。 - Integer 字段:用于存储整数。例如,添加一个订单数量字段:
order_quantity = fields.Integer(string='Order Quantity')
- Float 字段:用于存储浮点数,常用于金额、价格等。例如,添加一个订单金额字段:
其中,order_amount = fields.Float(string='Order Amount', digits=(10, 2))
digits
参数用于指定浮点数的精度,如(10, 2)
表示最多 10 位数字,其中小数部分占 2 位。 - Boolean 字段:用于存储布尔值,表示是/否的状态。例如,添加一个是否已发货字段:
其中,is_shipped = fields.Boolean(string='Is Shipped', default=False)
default
参数用于指定字段的默认值。 - Date 和 Datetime 字段:分别用于存储日期和日期时间。例如,添加一个订单日期字段:
其中,order_date = fields.Date(string='Order Date', default=fields.Date.today)
default
参数使用fields.Date.today
方法为字段设置默认值为当前日期。 - Selection 字段:用于存储一组预定义的选项。例如,添加一个订单状态字段:
其中,选项以元组列表的形式定义,每个元组的第一个元素是选项的值,第二个元素是选项的显示名称。order_status = fields.Selection([ ('draft', 'Draft'), ('confirmed', 'Confirmed'), ('shipped', 'Shipped'), ('done', 'Done') ], string='Order Status', default='draft')
- Many2one 字段:用于建立模型之间的关联关系,表示多对一的关系。例如,销售订单关联到客户模型:
其中,customer_id = fields.Many2one('res.partner', string='Customer')
res.partner
是 Odoo 中客户模型的名称,customer_id
字段将销售订单与客户模型关联起来,可以通过该字段访问客户的相关信息。 - One2many 字段:用于表示一对多的关系,通常与 Many2one 字段配合使用。例如,在客户模型中添加一个字段来关联其所有的销售订单:
这样,客户模型可以通过sale_order_ids = fields.One2many('custom.sale.order', 'customer_id', string='Sales Orders')
sale_order_ids
字段访问其所有的销售订单记录。 - Many2many 字段:用于表示多对多的关系。例如,销售订单与产品之间的多对多关系:
其中,product_ids = fields.Many2many('product.product', string='Products')
product.product
是 Odoo 中产品模型的名称,product_ids
字段表示销售订单与多个产品之间的关联关系。
通过合理地定义模型类和添加字段,可以构建出满足业务需求的数据结构,为 Odoo 模块的开发奠定坚实的基础。# 5. 视图与用户界面
5.1 创建列表视图
在 Odoo 中,列表视图用于以表格形式展示数据,是用户界面的重要组成部分。以下是创建列表视图的详细步骤和注意事项:
定义视图文件:列表视图通常定义在模块的
views
目录下的 XML 文件中。例如,在custom_sales
模块中,可以在views
目录下创建一个sale_order_views.xml
文件来定义销售订单的列表视图。视图的基本结构:列表视图通过
<tree>
标签定义,其中可以包含多个<field>
标签来指定要显示的字段。例如,定义一个简单的销售订单列表视图:<record id="view_sale_order_tree" model="ir.ui.view"> <field name="name">custom.sale.order.tree</field> <field name="model">custom.sale.order</field> <field name="arch" type="xml"> <tree string="Sales Orders"> <field name="order_number"/> <field name="customer_id"/> <field name="order_date"/> <field name="order_amount"/> <field name="order_status"/> </tree> </field> </record>
id
:视图的唯一标识,用于在 Odoo 系统中引用该视图。model
:指定该视图对应的模型名称,这里是custom.sale.order
。<tree>
标签:定义列表视图的结构,string
属性是视图的标题。<field>
标签:指定要显示的字段,字段名称必须与模型中定义的字段名称一致。
字段排序与显示:可以通过
<field>
标签的sequence
属性来控制字段的显示顺序。例如:<field name="order_number" sequence="1"/> <field name="customer_id" sequence="2"/>
数字越小,字段越靠前。
字段显示格式:对于某些字段,可以指定显示格式。例如,对于日期字段,可以通过
options
属性设置显示格式:<field name="order_date" options="{'format': 'dd/mm/yyyy'}"/>
添加操作按钮:可以在列表视图中添加操作按钮,例如添加一个“确认订单”按钮:
<tree string="Sales Orders"> <field name="order_number"/> <field name="customer_id"/> <field name="order_date"/> <field name="order_amount"/> <field name="order_status"/> <button name="action_confirm" string="Confirm" type="object" class="oe_highlight"/> </tree>
name
:按钮调用的方法名称,必须在模型中定义。string
:按钮的显示文本。type
:按钮的类型,object
表示调用模型中的方法。class
:按钮的样式类,oe_highlight
用于突出显示按钮。
5.2 设计表单视图
表单视图用于展示和编辑单个记录的详细信息,是用户界面中另一个重要的视图类型。以下是设计表单视图的详细步骤和注意事项:
定义表单视图文件:表单视图同样定义在模块的
views
目录下的 XML 文件中。例如,在custom_sales
模块的sale_order_views.xml
文件中定义销售订单的表单视图。视图的基本结构:表单视图通过
<form>
标签定义,其中可以包含多个<group>
、<field>
、<button>
等标签来组织和显示字段。例如:<record id="view_sale_order_form" model="ir.ui.view"> <field name="name">custom.sale.order.form</field> <field name="model">custom.sale.order</field> <field name="arch" type="xml"> <form string="Sale Order"> <sheet> <group> <field name="order_number"/> <field name="customer_id"/> <field name="order_date"/> </group> <group> <field name="order_amount"/> <field name="order_status"/> </group> </sheet> <footer> <button name="action_confirm" string="Confirm" type="object" class="oe_highlight"/> <button string="Cancel" special="cancel"/> </footer> </form> </field> </record>
id
:视图的唯一标识。model
:指定该视图对应的模型名称。<form>
标签:定义表单视图的结构,string
属性是视图的标题。<sheet>
标签:用于组织表单内容,使其更具可读性。<group>
标签:用于分组显示字段,方便用户查看和编辑。<field>
标签:指定要显示的字段。<footer>
标签:用于放置操作按钮,如“确认”和“取消”按钮。
字段显示方式:可以通过
<field>
标签的widget
属性来指定字段的显示方式。例如,对于文本字段,可以使用textarea
小部件:<field name="description" widget="textarea"/>
字段默认值:可以通过
<field>
标签的default
属性为字段设置默认值。例如:<field name="order_status" default="draft"/>
字段只读模式:可以通过
<field>
标签的readonly
属性设置字段在某些情况下为只读。例如:<field name="order_number" readonly="1"/>
关联字段的显示:对于 Many2one 字段,可以通过
<field>
标签的domain
属性来限制可选择的记录。例如:<field name="customer_id" domain="[('is_customer', '=', True)]"/>
通过以上步骤,可以创建和设计出满足业务需求的列表视图和表单视图,为用户提供直观且易于操作的用户界面。# 6. 安全与权限设置
6.1 定义访问控制规则
在 Odoo 中,访问控制规则是确保数据安全和用户权限管理的关键机制。通过定义访问控制规则,可以精确地控制用户对数据的访问权限,包括读、写、创建和删除等操作。以下是定义访问控制规则的详细步骤和注意事项:
访问控制规则文件:访问控制规则通常定义在模块的
data
目录下的 XML 文件中。例如,在custom_sales
模块中,可以在data
目录下创建一个security.xml
文件来定义访问控制规则。规则的基本结构:访问控制规则通过
<record>
标签定义,其中包含<field>
标签来指定规则的详细信息。例如,定义一个简单的访问控制规则:<record id="rule_sale_order_read" model="ir.rule"> <field name="name">Sale Order Read Access</field> <field name="model_id" ref="model_custom_sale_order"/> <field name="domain_force">[('order_status', '=', 'done')]</field> <field name="perm_read" eval="1"/> <field name="perm_write" eval="0"/> <field name="perm_create" eval="0"/> <field name="perm_delete" eval="0"/> <field name="groups" eval="[(4, ref('group_sales_manager'))]"/> </record>
id
:规则的唯一标识,用于在 Odoo 系统中引用该规则。model
:指定该规则对应的模型名称,这里是ir.rule
。name
:规则的名称,用于在 Odoo 界面中显示。model_id
:指定规则所应用的模型,通过ref
引用模型的外部标识符。domain_force
:定义规则的过滤条件,只有满足该条件的记录才会受到该规则的约束。例如,[('order_status', '=', 'done')]
表示该规则只对订单状态为done
的记录生效。perm_read
、perm_write
、perm_create
、perm_delete
:分别表示读、写、创建和删除权限,eval="1"
表示允许,eval="0"
表示禁止。groups
:指定该规则适用的用户组,通过ref
引用用户组的外部标识符。
规则的作用范围:访问控制规则可以全局生效,也可以仅对特定用户组生效。通过在
groups
字段中指定用户组,可以实现对不同用户组的差异化权限管理。例如,上述规则仅对销售经理组(group_sales_manager
)生效。规则的优先级:当多个规则同时适用时,Odoo 会根据规则的定义顺序和优先级进行综合判断。默认情况下,规则的优先级由其定义顺序决定,先定义的规则优先级更高。如果需要调整规则的优先级,可以通过
sequence
属性进行设置。
通过合理地定义访问控制规则,可以确保用户只能访问和操作其权限范围内的数据,从而提高系统的安全性和数据的完整性。
6.2 创建用户组
用户组是 Odoo 中用于管理用户权限的重要工具,通过创建用户组并分配不同的权限,可以实现对用户的精细化管理。以下是创建用户组的详细步骤和注意事项:
用户组文件:用户组通常定义在模块的
data
目录下的 XML 文件中。例如,在custom_sales
模块中,可以在data
目录下创建一个security.xml
文件来定义用户组。用户组的基本结构:用户组通过
<record>
标签定义,其中包含<field>
标签来指定用户组的详细信息。例如,定义一个销售经理用户组:<record id="group_sales_manager" model="res.groups"> <field name="name">Sales Manager</field> <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/> </record>
id
:用户组的唯一标识,用于在 Odoo 系统中引用该用户组。model
:指定该用户组对应的模型名称,这里是res.groups
。name
:用户组的名称,用于在 Odoo 界面中显示。implied_ids
:指定该用户组所包含的其他用户组,通过ref
引用其他用户组的外部标识符。例如,base.group_user
是 Odoo 默认的用户组,表示普通用户组。
用户组的权限分配:用户组的权限通过访问控制规则进行分配。在定义访问控制规则时,通过
groups
字段指定该规则适用的用户组,从而实现对用户组的权限管理。例如,上述访问控制规则仅对销售经理组(group_sales_manager
)生效,这意味着销售经理组的用户将获得相应的权限。用户组的层级关系:用户组之间可以存在层级关系,一个用户组可以包含多个子用户组。通过在
implied_ids
字段中指定子用户组,可以实现用户组的层级结构。例如,定义一个销售员用户组,并将其包含在销售经理组中:<record id="group_sales_user" model="res.groups"> <field name="name">Sales User</field> <field name="implied_ids" eval="[(4, ref('group_sales_manager'))]"/> </record>
这样,销售员用户组的用户将自动继承销售经理组的权限。
用户组的使用场景:用户组可以用于多种场景,例如:
- 模块访问权限:通过用户组控制用户对特定模块的访问权限。例如,只有销售经理组的用户才能访问销售模块。
- 数据访问权限:通过用户组结合访问控制规则,控制用户对特定数据的访问权限。例如,只有销售经理组的用户才能查看已完成的销售订单。
- 功能权限:通过用户组控制用户对特定功能的使用权限。例如,只有销售经理组的用户才能创建新的销售订单。
通过创建合理的用户组并分配适当的权限,可以实现对用户的精细化管理,确保系统的安全性和数据的完整性,同时提高用户的操作效率和用户体验。# 7. 测试与调试
7.1 启动 Odoo 服务
启动 Odoo 服务是测试模块功能的第一步,确保开发环境正常运行。在命令行中运行以下命令启动 Odoo 服务器:
python odoo-bin -c odoo.conf
如果启动成功,可以通过浏览器访问 http://localhost:8069
来查看 Odoo 的登录页面。在启动过程中,需要确保以下几点:
- 配置文件正确:
odoo.conf
配置文件中指定的数据库连接信息、语言、日志级别、管理员密码和 HTTP 端口等参数必须正确无误。 - 依赖环境完整:确保所有 Python 依赖已正确安装,包括
libsass
等可能需要额外编译的库。 - 数据库可用:确保 PostgreSQL 数据库已正确安装,并且创建了对应的数据库用户和数据库。
启动过程中可能会遇到的问题及解决方法:
- 端口冲突:如果
http_port
指定的端口被其他应用占用,可以修改配置文件中的端口号,例如改为8070
。 - 依赖缺失:如果某些依赖未正确安装,可能会导致启动失败。可以通过运行
pip install -r requirements.txt
来重新安装依赖。 - 数据库连接失败:检查数据库用户密码是否正确,以及数据库服务是否已启动。
7.2 测试模块功能
测试模块功能是确保开发的模块能够正常运行并满足业务需求的关键步骤。以下是测试模块功能的具体方法和注意事项:
功能测试
- 用户界面测试:登录 Odoo 系统,进入模块的应用程序,检查用户界面是否正常显示。例如,检查自定义模块的列表视图和表单视图是否正确加载,字段是否显示正常。
- 数据操作测试:测试数据的增删改查功能是否正常。例如,在销售订单模块中,创建一个新的销售订单,检查是否可以成功保存;修改已存在的销售订单,检查修改后的数据是否正确保存;删除销售订单,检查是否能够成功删除。
- 关联关系测试:如果模块中定义了模型之间的关联关系,例如 Many2one、One2many 或 Many2many 字段,需要测试这些关联关系是否正常工作。例如,检查销售订单是否能够正确关联到客户模型,以及客户模型是否能够正确显示其所有的销售订单。
权限测试
- 访问控制规则测试:根据定义的访问控制规则,测试不同用户组的权限是否正确。例如,对于销售经理组,检查是否能够读取已完成的销售订单,而对于普通用户组,检查是否无法读取这些订单。
- 用户组权限测试:测试用户组的权限分配是否正确。例如,检查销售员用户组是否能够创建新的销售订单,但无法删除订单。
性能测试
- 加载时间测试:测试模块的加载时间是否合理。例如,检查销售订单列表视图的加载时间是否在可接受范围内,如果加载时间过长,可能需要优化查询语句或数据库索引。
- 并发测试:如果模块需要支持高并发操作,可以使用工具进行并发测试,检查系统在高并发情况下的性能表现。
日志与错误处理
- 日志查看:查看 Odoo 的日志文件,检查是否有错误信息或警告信息。日志文件通常位于配置文件中指定的日志路径,例如
log_level = info
时,日志文件会记录详细的信息。 - 错误处理:如果在测试过程中遇到错误,需要根据错误信息进行排查和修复。常见的错误包括数据库查询错误、Python 代码错误等。
通过以上测试步骤,可以全面验证自定义模块的功能是否正常,确保模块能够满足业务需求并稳定运行。
半小时入门 odoo