JavaScript 参考¶
本文档介绍了 Odoo JavaScript 框架。该框架从代码行数来看并不是一个大型应用程序,但它的通用性很强,因为它基本上是一台将声明性界面描述转化为实时应用程序的机器,能够与数据库中的每个模型和记录进行交互。甚至可以使用 Web 客户端来修改 Web 客户端的界面。
概述¶
JavaScript 框架旨在处理以下三个主要用例:
Web 客户端:这是私有的 Web 应用程序,用户可以在其中查看和编辑业务数据。这是一个单页应用程序(页面永远不会重新加载,仅在需要时从服务器获取新数据)。
网站:这是 Odoo 的公共部分。它允许未识别的用户浏览内容、购物或作为客户执行许多操作。这是一个经典的网站:具有各种路由、控制器以及一些使功能运行的 JavaScript。
销售点:这是销售点的界面。它是一个专门的单页应用程序。
某些 JavaScript 代码对这三个用例是通用的,并被打包在一起(详见下文的资源部分)。本文档将主要关注 Web 客户端的架构。
Web 客户端¶
单页应用程序¶
Web 客户端是一个单页应用程序:当用户执行操作时,它不会每次都向服务器请求完整页面,而只会加载更新用户界面(UI)所需的资源。在此过程中,它还会更新 URL 中的信息,因此在大多数情况下,刷新页面或关闭浏览器后重新打开会显示相同的内容。
Web 客户端 JS 代码概览¶
在这里,我们快速概述了 web
插件中的 Web 客户端代码。路径将相对于 web/static/src
描述。以下描述并非详尽无遗;其目标只是让读者对架构有一个整体的认识。
module_loader.js
:这是定义 Odoo JavaScript 模块系统的文件。它需要在任何其他 JS 模块之前加载。core/
:此文件夹包含构成 JavaScript 框架最低层的代码,这些代码可用于 Web 客户端、网站、门户以及销售点应用程序。weblient/
:此文件夹包含特定于 Web 客户端的文件,无法在网站或销售点中使用,例如动作管理器和动作服务。webclient/webclient.js
:这是 Web 客户端组件本身。它主要是动作容器和导航栏的包装器,并执行一些启动应用程序时所需的操作,例如加载 URL 的状态。webclient/actions/
:此文件夹包含负责显示和切换动作的代码。views/
:此文件夹包含视图基础设施的代码以及大多数视图(某些类型的视图由其他插件添加)。views/fields/
:包含各种字段组件的定义,以及多个字段使用的实用工具。search/
:所有这些文件定义了搜索视图(从 Web 客户端的角度来看,它不是一个视图,仅从服务器的角度来看是)。
如果文件未加载/更新该怎么办¶
文件未能正确加载的原因可能有很多。以下是您可以尝试解决该问题的一些方法:
确保您已保存文件;忘记保存这种事可能发生在任何人身上。
查看控制台(在开发者工具中,通常通过 F12 打开)并检查是否有错误。
尝试在文件开头添加一个
console.log()
,以便查看文件是否已加载。如果未加载,可能是它不在正确的资源包中,或者资源包未更新。根据您的设置,服务器可能不会在文件修改后重新生成资源包;以下是几种解决方法:
重启服务器将强制其在下次请求时检查资源包是否最新。
在调试模式下,调试菜单中有一个选项(导航栏中的 按钮),可以强制服务器在不重启的情况下动态重新生成资源包。
使用
--dev=xml
选项启动服务器将强制服务器在每次请求时检查资源包是否最新。我们建议您在积极开发时使用此选项,但不要在生产环境中使用。
更改代码后,请确保刷新页面。Odoo 目前没有热模块重载机制。
加载 JavaScript 代码¶
大型应用程序通常会被拆分为较小的文件,这些文件需要相互连接。某些文件可能需要使用另一个文件中定义的代码。文件之间共享代码有两种方式:
使用全局作用域(即 window 对象)来读取或写入对某些对象或函数的引用,
使用模块系统,该系统为每个模块提供导出或导入值的方式,并确保它们以正确的顺序加载。
虽然可以在全局作用域中工作,但这存在一些问题:
很难确保实现细节不被暴露:全局作用域中的函数声明可被所有其他代码访问。
只有一个命名空间,这很容易导致命名冲突。
依赖关系是隐式的:如果一段代码依赖于另一段代码,则它们的加载顺序很重要,但难以保证。
使用模块系统有助于解决这些问题:因为模块会指定其依赖项,模块系统可以按正确的顺序加载它们,或者在依赖项缺失或循环依赖时发出错误。模块还形成自己的命名空间,并可以选择要导出的内容,从而防止实现细节的暴露和命名冲突。
虽然我们可以直接使用 ECMAScript(ES)模块,但这种方法存在一些缺点:每个 ES 模块都需要一次网络往返,当有数百个文件时,这会变得非常缓慢。此外,Odoo 中的许多文件尽管未被任何内容导入,但仍需存在,因为它们只是简单地添加了框架使用的代码,而不是反过来。
因此,Odoo 有一套资源包系统。在这些资源包中,JavaScript 文件是带有顶部特殊注解的 ES 模块。这些模块将被打包在一起并转译,以便我们的模块加载器使用。虽然您可以编写不使用此模块系统的代码,但通常不建议这样做。
(参见 原生 JavaScript 模块)
修补类¶
尽管我们尽力提供无需这样做的扩展点,但有时确实需要就地修改现有类的行为。目标是拥有一种机制,能够更改类及其所有未来/当前实例。这是通过使用 patch
工具函数完成的:
import { Hamster } from "@web/core/hamster"
import { patch } from "@web/core/utils/patch";
patch(Hamster.prototype, {
sleep() {
super.sleep(...arguments);
console.log("zzzz");
},
});
修补方法时,您需要修补类的原型;但如果您想修补类的静态属性,则需要修补类本身。
修补是一项危险的操作,应谨慎执行,因为它将修改类的所有实例,即使它们已经被创建。为避免奇怪的问题,应在模块的顶层尽早应用修补。如果类已经被实例化,在运行时修补类可能会导致极其难以调试的问题。
Registries注册表¶
在 Odoo 生态系统中,一个常见的需求是从外部(通过安装应用程序,即不同的模块)扩展或更改基础系统的行为。例如,可能需要在某些视图中添加一个新的字段部件。在这种情况下以及许多其他情况下,通常的流程是创建所需的组件,然后将其添加到注册表中(注册步骤),以便让 Web 客户端的其余部分知道它的存在。
系统中有几个可用的注册表。框架使用的注册表是主注册表中的类别,可以从 @web/core/registry
导入。
- 字段注册表
字段注册表包含 Web 客户端已知的所有字段部件。每当视图(通常是表单或列表/看板)需要字段部件时,它都会在这里查找。一个典型的用例如下:
import { registry } from "@web/core/registry"; class PadField extends Component { ... } registry.category("fields").add("pad", { component: PadField, supportedTypes: ["char"], // ... });
- 视图注册表
此注册表包含 Web 客户端已知的所有 JS 视图。
- 动作注册表
我们在此注册表中跟踪所有客户端动作。这是动作管理器在需要创建客户端动作时查找的地方。客户端动作可以是一个函数——当调用该动作时会调用该函数,并且返回值将在需要时作为后续动作执行——或者是一个在执行该动作时显示的 Owl 组件。
Services服务¶
在 Web 客户端中,有些问题无法由单个组件处理,因为这些问题具有横向性、涉及多个组件,或者需要在应用程序的整个生命周期内保持某种状态。
服务是解决这些问题的一种方案:它们在应用程序启动期间创建,通过 useService
钩子供组件使用,并在整个应用程序的生命周期内保持活动状态。
例如,我们有 orm 服务,其作用是允许与服务器上的业务对象进行交互。
以下是一个关于如何实现 orm 服务的简化示例:
import { registry } from "@web/core/registry";
export const OrmService = {
start() {
return {
read(...) { ... },
write(...) { ... },
unlink(...) { ... },
...
}
},
};
registry.category("services").add("orm", OrmService);
使用服务¶
服务在环境中可用,但通常应通过 useService
钩子使用,它可以防止在组件被销毁后调用服务上的方法,并在调用期间组件被销毁时防止进一步执行代码。
class SomeComponent extends Component {
setup() {
this.orm = useService("orm");
}
// ...
getActivityModelViewID(model) {
return this.orm.call(model, "get_activity_view_id", this.params);
}
}
与服务器通信¶
在 Odoo 开发中,通常有两种用例:一种可能需要调用 Python 模型上的方法(这会通过控制器 /web/dataset/call_kw
),另一种可能需要直接调用某个路由上可用的控制器。
调用 Python 模型上的方法是通过 orm 服务完成的:
return this.orm.call("some.model", "some_method", [some, args]);
直接调用控制器是通过 rpc 服务完成的:
return this.rpc("/some/route/", { some: param, });
注解
rpc 服务实际上并不执行通常意义上的远程过程调用(RPC),但由于历史原因,在 Odoo 中我们通常将 JavaScript 中执行的任何网络请求称为 RPC。正如前文所述,如果您想调用模型上的方法,应该使用 orm 服务。
通知¶
Odoo 框架有一种标准方式向用户传递各种信息:通知,它们会显示在用户界面的右上角。通知的类型遵循 Bootstrap 的提示框样式:
info:用于显示某些不会失败的操作所产生的信息反馈。
success:用户执行了一个可能失败但未失败的操作。
warning:用户执行了一个只能部分完成的操作。当某些事情出错但并非由用户直接引起或无法特别处理时也非常有用。
danger:用户尝试执行某个操作但未能完成。
通知还可用于在不打扰用户工作流程的情况下向用户提问。例如,通过 VOIP 接收到的电话:可以显示一个带有 接受 或 拒绝 两个按钮的粘性通知。
显示通知¶
在 Odoo 中显示通知有两种方式:
notification 服务允许组件通过调用
add
方法从 JavaScript 代码中显示通知。display_notification 客户端动作允许从 Python 触发通知的显示(例如,在用户点击对象类型按钮时调用的方法中)。此客户端动作使用通知服务。
通知有一些 选项:
title:字符串,可选。它将作为标题显示在顶部。
message:字符串,可选。通知的内容。可以是用于显示格式化文本的标记对象。
sticky:布尔值,可选(默认为 false)。如果为 true,通知将一直保留,直到用户手动关闭它。否则,通知将在短时间后自动关闭。
type:字符串,可选(默认为 “warning”)。确定通知的样式。可能的值:”info”、”success”、”warning”、”danger”。
className:字符串,可选。这是一个将自动添加到通知中的 CSS 类名。尽管不建议使用,但它在样式设置方面可能会有所帮助。
以下是一些如何在 JavaScript 中显示通知的示例:
// note that we call _t on the text to make sure it is properly translated.
this.notification.add({
title: _t("Success"),
message: _t("Your signature request has been sent.")
});
this.notification.add({
title: _t("Error"),
message: _t("Filter name is required."),
type: "danger",
});
而在 Python 中:
# note that we call _(string) on the text to make sure it is properly translated.
def show_notification(self):
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Your signature request has been sent.'),
'sticky': False,
}
}
系统托盘¶
系统托盘是界面中导航栏的右侧部分,Web 客户端在此处显示一些小部件,例如消息菜单。
当导航栏创建系统托盘时,它会查找所有已注册的系统托盘项并显示它们。
目前没有针对系统托盘项的特定 API。它们是 Owl 组件,可以通过与其他组件相同的方式与环境交互,例如通过与服务交互。
添加新的系统托盘项¶
可以通过将项目添加到 “systray” 注册表中来将其添加到系统托盘:
import { registry } from "@web/core/registry"
class MySystrayComponent extends Component {
...
}
registry.category("systray").add("MySystrayComponent", MySystrayComponent, { sequence: 1 });
项目会根据其在系统托盘注册表中的顺序排列。
翻译管理¶
一些翻译是在服务器端完成的(基本上是所有由服务器渲染或处理的文本字符串),但静态文件中也有一些字符串需要翻译。当前的工作方式如下:
每个可翻译的字符串都通过特殊函数 _t 进行标记。
这些字符串被服务器用来生成适当的 PO 文件。
每当加载 Web 客户端时,它都会调用路由 /web/webclient/translations,该路由返回所有可翻译术语的列表。
在运行时,每当调用
_t
函数时,它会在该列表中查找以找到翻译,并在未找到翻译时返回原始字符串。
请注意,有关翻译的更多详细信息(从服务器的角度)可以在文档 模块翻译 中找到。
import { _t } from "@web/core/l10n/translation";
class SomeComponent extends Component {
static exampleString = _t("this should be translated");
...
someMethod() {
const str = _t("some text");
}
}
请注意,使用翻译函数需要格外小心:作为参数提供的字符串不能是动态的,因为它会从代码中静态提取以生成 PO 文件,并作为要翻译术语的标识符。如果需要在字符串中注入动态内容,_t
支持占位符:
import { _t } from "@web/core/l10n/translation";
const str = _t("Hello %s, you have %s unread messages.", user.name, unreadCount);
注意字符串本身是固定的。这允许翻译函数在使用它进行插值之前检索已翻译的字符串。
会话¶
Web 客户端需要一些来自 Python 的信息才能正常运行。为了避免通过 JavaScript 发起网络请求而导致与服务器的额外往返,这些信息会被直接序列化到页面中,并可以通过 @web/session
模块在 JavaScript 中访问。
向会话添加信息¶
当加载 /web
路由时,服务器会将此信息注入到一个脚本标签中。这些信息是通过调用模型 ir.http
的 session_info
方法获得的。您可以通过重写此方法向返回的字典中添加信息。
from odoo import models
from odoo.http import request
class IrHttp(models.AbstractModel):
_inherit = 'ir.http'
def session_info(self):
result = super(IrHttp, self).session_info()
result['some_key'] = get_some_value_from_db()
return result
现在,可以通过在会话中读取来获取 JavaScript 中的值:
import { session } from "@web/session"
const myValue = session.some_key;
...
请注意,此机制旨在减少 Web 客户端准备就绪所需的通信量。它仅适用于计算成本较低的数据(缓慢的 session_info 调用会延迟所有用户的 Web 客户端加载),以及在初始化过程早期需要的数据。
视图¶
“视图”一词有多种含义。本节讨论的是视图的 JavaScript 代码设计,而不是 arch 的结构或其他内容。
虽然视图只是 Owl 组件,但内置视图通常具有相同的结构:一个名为 “SomethingController” 的组件作为视图的根。此组件创建某个 “model”(负责管理数据的对象)的实例,并具有一个名为 “renderer” 的子组件,用于处理显示逻辑。
字段¶
Web 客户端体验的很大一部分涉及编辑和创建数据。大部分工作是在字段部件的帮助下完成的,这些部件了解字段类型以及如何显示和编辑值的具体细节。
装饰¶
与列表视图类似,字段部件也对装饰提供简单支持。装饰的目标是提供一种简单的方法,根据记录的当前状态指定文本颜色。例如:
<field name="state" decoration-danger="amount < 10000"/>
有效的装饰名称包括:
decoration-bf
decoration-it
decoration-danger
decoration-info
decoration-muted
decoration-primary
decoration-success
decoration-warning
每个装饰 decoration-X 将映射到一个 CSS 类 text-X,这是一个标准的 Bootstrap CSS 类(text-it 和 text-bf 除外,它们由 Odoo 处理,分别对应斜体和粗体)。请注意,装饰属性的值应为有效的 Python 表达式,并将以记录作为评估上下文进行求值。
非关系字段¶
我们在此记录所有默认可用的非关系字段,顺序不分先后。
- 整数 (
integer
) 这是类型为
integer
的字段的默认字段类型。支持的字段类型:
integer
选项:
type
:设置输入类型(默认为"text"
,可设置为"number"
)在编辑模式下,该字段被渲染为一个 HTML 属性类型为
"number"
的输入框(以便用户可以受益于原生支持,尤其是在移动设备上)。在这种情况下,默认格式化会被禁用以避免不兼容问题。<field name="int_value" options="{'type': 'number'}" />
step
:设置当用户点击按钮时数值增减的步长(仅适用于类型为数字的输入框,默认为1
)<field name="int_value" options="{'type': 'number', 'step': 100}" />
format
:是否应对数字进行格式化(默认为true
)。默认情况下,数字会根据区域设置参数进行格式化。此选项将防止字段值被格式化。
<field name="int_value" options='{"format": false}' />
- 浮点数 (
float
) 这是类型为
float
的字段的默认字段类型。支持的字段类型:
float
属性:
digits
:显示精度<field name="factor" digits="[42,5]" />
选项:
type
:设置输入类型(默认为"text"
,可设置为"number"
)在编辑模式下,该字段被渲染为一个 HTML 属性类型为
"number"
的输入框(以便用户可以受益于原生支持,尤其是在移动设备上)。在这种情况下,默认格式化会被禁用以避免不兼容问题。<field name="int_value" options="{'type': 'number'}" />
step
:设置当用户点击按钮时数值增减的步长(仅适用于类型为数字的输入框,默认为1
)<field name="int_value" options="{'type': 'number', 'step': 0.1}" />
format
:是否应对数字进行格式化(默认为true
)。默认情况下,数字会根据区域设置参数进行格式化。此选项将防止字段值被格式化。
<field name="int_value" options="{'format': false}" />
- 时间 (
float_time
) 此部件的目标是以适当的方式显示表示时间间隔(以小时为单位)的浮点值。例如,
0.5
应格式化为0:30
,而4.75
对应于4:45
。支持的字段类型:
float
- 浮点因子 (
float_factor
) 此部件旨在根据其选项中提供的因子正确显示转换后的浮点值。例如,数据库中保存的值为
0.5
,因子为3
,则部件值应格式化为1.5
。支持的字段类型:
float
- 浮点切换 (
float_toggle
) 此部件的目标是用一个包含可能值范围(在选项中提供)的按钮替换输入框。每次点击允许用户在范围内循环选择。其目的是将字段值限制为预定义的选择。此外,该部件支持与
float_factor
部件相同的因子转换(范围值应为转换的结果)。支持的字段类型:
float
<field name="days_to_close" widget="float_toggle" options="{'factor': 2, 'range': [0, 4, 8]}" />
- 布尔值 (
boolean
) 这是类型为
boolean
的字段的默认字段类型。支持的字段类型:
boolean
- 字符 (
char
) 这是类型为
char
的字段的默认字段类型。支持的字段类型:
char
- 日期 (
date
) 这是类型为
date
的字段的默认字段类型。它由一个文本框和一个日期选择器组成。支持的字段类型:
date
选项:
min_date
/max_date
:设置可接受值的日期限制。默认情况下,最早接受的日期是 1000-01-01,最晚是 9999-12-31。可接受的值为 SQL 格式的日期(yyyy-MM-dd HH:mm:ss
)或"today"
。<field name="datefield" options="{'min_date': 'today', 'max_date': '2023-12-31'}" />
warn_future:如果值在未来(基于今天),则显示警告。
<field name="datefield" options="{'warn_future': true}" />
- 日期和时间 (
datetime
) 这是类型为
datetime
的字段的默认字段类型。值始终在客户端的时区中。支持的字段类型:
datetime
选项:
参见 日期字段 选项
rounding
:用于生成时间选择器中可用分钟数的增量。这不会影响实际值,仅影响下拉菜单中可用选项的数量(默认值:5
)。<field name="datetimefield" options="{'rounding': 10}" />
show_seconds
:当设置为 false 时,隐藏日期时间字段中的秒数。字段仍将接受日期时间值,但秒数将在界面中隐藏(默认值:true
)。<field name="datetimefield" widget="datetime" options="{'show_seconds': false}" />
show_time
:当设置为 false 时,隐藏日期时间字段中的时间部分。字段仍将接受日期时间值,但时间部分将在界面中隐藏(默认值:true
)。<field name="datetimefield" widget="datetime" options="{'show_time': false}" />
- 日期范围 (
daterange
) 此部件允许用户从单个选择器中选择开始日期和结束日期。
支持的字段类型:
date
、datetime
选项:
start_date_field
:用于获取/设置日期范围起始值的字段(不能与end_date_field
一起使用)。<field name="end_date" widget="daterange" options="{'start_date_field': 'start_date'}" />
end_date_field
:用于获取/设置日期范围结束值的字段(不能与start_date_field
一起使用)。<field name="start_date" widget="daterange" options="{'end_date_field': 'end_date'}" />
- 剩余天数 (
remaining_days
) 此部件可用于日期和日期时间字段。在只读模式下,它显示字段值与今天的差值(以天为单位)。在编辑模式下,该部件会变为常规的日期或日期时间字段。
支持的字段类型:
date
、datetime
- 货币 (
monetary
) 这是类型为
monetary
的字段的默认字段类型。它用于显示货币。如果选项中提供了货币字段,则会使用该字段;否则将回退到会话中的默认货币。支持的字段类型:
monetary
、float
选项:
currency_field
:另一个字段名称,应该是货币的多对一字段。<field name="value" widget="monetary" options="{'currency_field': 'currency_id'}" />
- 文本 (
text
) 这是类型为
text
的字段的默认字段类型。支持的字段类型:
text
- 手柄 (
handle
) 此字段的作用是显示为一个
手柄
,并允许通过拖放来重新排序各个记录。警告
必须在记录排序所依据的字段上指定它。
警告
在同一列表中拥有多个带手柄部件的字段是不受支持的。
支持的字段类型:
integer
- 电子邮件 (
email
) 此字段显示电子邮件地址。使用它的主要原因是,在只读模式下,它会被渲染为带有正确 href 的锚标签。
支持的字段类型:
char
- 电话 (
phone
) 此字段显示电话号码。使用它的主要原因是,在只读模式下,它会被渲染为带有正确 href 的锚标签,但仅在某些情况下:只有当设备可以拨打该特定号码时,我们才希望它是可点击的。
支持的字段类型:
char
- URL (
url
) 此字段显示 URL(在只读模式下)。使用它的主要原因是,它会被渲染为带有适当 CSS 类和 href 的锚标签。
此外,可以通过 text 属性自定义锚标签的文本(不会改变 href 值)。
支持的字段类型:
char
<field name="foo" widget="url" text="Some URL" />
选项:
website_path
:(默认值:false
)默认情况下,该部件强制(如果不是的话)href 值以"http://"
开头,除非此选项设置为true
,从而允许重定向到数据库自身的网站。
- 域 (
domain
) domain
字段允许用户通过树状界面构建技术前缀域,并实时查看所选记录。在调试模式下,还提供了一个输入框,可以直接输入前缀字符域(或构建树状界面不支持的高级域)。请注意,这仅限于 静态 域(无动态表达式或上下文变量访问)。
支持的字段类型:
char
选项:
model
:编码应用域的res_model
的字符字段名称。foldable`(默认值:`false
):如果为 true,域字段将以紧凑形式渲染,并在用户交互时展开。in_dialog`(默认值:`false
):如果为 true,当用户想要编辑域时,部件会打开一个对话框;而默认情况下,域编辑器会直接渲染在值的下方。
- 链接按钮 (
link_button
) LinkButton
部件实际上只是显示一个带有图标和文本值的 span 元素。该链接是可点击的,并会在新浏览器窗口中以其值作为 URL 打开。支持的字段类型:
char
- 图像文件 (
image
) 此部件用于将二进制值表示为图像。在某些情况下,服务器会返回
bin_size
而非实际图像(bin_size
是表示文件大小的字符串,例如"6.5kb"
)。在这种情况下,部件会生成一个图像,其源属性对应于服务器上的图像。支持的字段类型:
binary
选项:
preview_image
:如果图像仅以bin_size
形式加载,则此选项可用于告知 Web 客户端,默认字段名称不是当前字段的名称,而是另一个字段的名称。<field name="image" widget="image" options="{'preview_image': 'image_128'}" />
accepted_file_extensions
:用户可以从文件输入对话框中选择的文件扩展名(默认值为"image/*"
)。(参见
<input type="file" />
的accept
属性)
- 二进制文件 (
binary
) 通用部件,用于保存/下载二进制文件。
支持的字段类型:
binary
属性:
filename
:保存二进制文件时会丢失其文件名,因为它仅保存二进制值。文件名可以保存在另一个字段中。为此,应将filename
属性设置为视图中存在的字段。<field name="datas" filename="datas_fname" />
选项:
accepted_file_extensions
:用户可以从文件输入对话框中选择的文件扩展名(参见
<input type="file" />
的accept
属性)
- 优先级 (
priority
) 此部件被渲染为一组星形,允许用户点击以选择或不选择某个值。例如,这可用于将任务标记为高优先级。
请注意,此部件也可以在
readonly
模式下工作,这是不常见的。支持的字段类型:
selection
- 图像附件 (
attachment_image
) 适用于
many2one
字段的图像部件。如果字段已设置,此部件将渲染为具有适当 src URL 的图像。此部件在编辑模式或只读模式下没有不同行为,仅用于查看图像。支持的字段类型:
many2one
<field name="displayed_image_id" widget="attachment_image" />
- 标签选择 (
label_selection
) 此部件渲染为一个简单的不可编辑标签。它仅用于显示某些信息,而不是编辑信息。
支持的字段类型:
selection
选项:
classes
:从选择值到 CSS 类名的映射<field name="state" widget="label_selection" options="{ 'classes': { 'draft': 'default', 'cancel': 'default', 'none': 'danger', }, }" />
- 状态选择 (
state_selection
) 这是一个专用的选择部件。它假设记录中存在一些硬编码字段,例如视图中的
stage_id
、legend_normal
、legend_blocked
、legend_done
。它主要用于显示和更改项目中任务的状态,并在下拉菜单中显示附加信息。支持的字段类型:
selection
<field name="kanban_state" widget="state_selection" />
- 状态选择 - 列表视图 (
list.state_selection
) 在列表视图中,
state_selection
字段默认会在图标旁边显示标签。支持的字段类型:
selection
选项:
hide_label
:隐藏图标旁边的标签<field name="kanban_state" widget="state_selection" options="{'hide_label': true}" />
- 收藏 (
boolean_favorite
) 此部件根据布尔值显示为空(或非空)的星形。请注意,它也可以在只读模式下编辑。
支持的字段类型:
boolean
- 开关 (
boolean_toggle
) 显示一个开关以表示布尔值。这是
boolean
字段的一个子字段,主要用于呈现不同的外观。支持的字段类型:
boolean
- 统计信息 (
statinfo
) 此部件用于在
stat button
中表示统计信息。它基本上只是一个带有数字的标签。支持的字段类型:
integer
、float
选项:
label_field
:如果提供,部件将使用label_field
的值作为文本。<button name="%(act_payslip_lines)d" icon="fa-money" type="action" > <field name="payslip_count" widget="statinfo" string="Payslip" options="{'label_field': 'label_tasks'}" /> </button>
- 百分比饼图 (
percentpie
) 此部件用于在
stat button
中表示统计信息。它类似于 statinfo 部件,但信息以 饼图 形式表示(从空到满)。请注意,该值被解释为百分比(介于0
和100
之间的数字)。支持的字段类型:
integer
、float
<field name="replied_ratio" string="Replied" widget="percentpie" />
- 进度条 (
progressbar
) 将值表示为进度条(从
0
到某个值)支持的字段类型:
integer
、float
选项:
editable
:布尔值,决定value
是否可编辑current_value
:从视图中必须存在的字段获取当前值max_value
:从视图中必须存在的字段获取最大值edit_max_value
:布尔值,决定max_value
是否可编辑title
:进度条的标题,显示在进度条上方-> 不会被翻译,如果需要翻译,请改用
title
属性(而非选项)
<field name="absence_of_today" widget="progressbar" options="{ 'current_value': 'absence_of_today', 'max_value': 'total_employee', 'editable': false, }" />
- 日记账仪表板图表 (
dashboard_graph
) 这是一个更专业的部件,用于显示代表一组数据的图表。例如,它用于会计仪表板的看板视图中。
它假设字段是一组数据的 JSON 序列化形式。
支持的字段类型:
char
属性:
graph_type
:字符串,可以是"line"
或"bar"
<field name="dashboard_graph_data" widget="dashboard_graph" graph_type="line" />
- Ace 编辑器 (
ace
) 此部件旨在用于文本字段。它提供 Ace 编辑器以编辑 XML 和 Python。
支持的字段类型:
char
、text
- 徽章 (
badge
) 在 Bootstrap 徽章药丸中显示值。
支持的字段类型:
char
、selection
、many2one
默认情况下,徽章的背景为浅灰色,但可以通过使用 装饰 机制进行自定义。例如,在给定条件下显示红色徽章:
<field name="foo" widget="badge" decoration-danger="state == 'cancel'" />
关系字段¶
选择 (selection
)
支持的字段类型:
selection
属性:
placeholder
:当未选择值时用于显示某些信息的字符串<field name="tax_id" widget="selection" placeholder="Select a tax" />
- 单选按钮 (
radio
) 这是
FielSelection
的一个子字段,专门用于将所有有效选项显示为单选按钮。请注意,如果用于 many2one 记录,则会执行更多 RPC 调用来获取相关记录的
name_get
。支持的字段类型:
selection
、many2one
选项:
horizontal
:如果为true
,单选按钮将水平显示。<field name="recommended_activity_type_id" widget="radio" options="{'horizontal': true}"/>
- 徽章选择 (
selection_badge
) 这是
selection
字段的一个子字段,专门用于将所有有效选项显示为矩形徽章。支持的字段类型:
selection
、many2one
<field name="recommended_activity_type_id" widget="selection_badge" />
- 多对一 (
many2one
) 多对一字段的默认部件。
支持的字段类型:
many2one
属性:
can_create
:允许创建相关记录(优先于no_create
选项)can_write
:允许编辑相关记录(默认值:true
)
选项:
quick_create
:允许快速创建相关记录(默认值:true
)no_create
:阻止创建相关记录——隐藏 创建 “xxx” 和 创建并编辑 下拉菜单项(默认值:false
)no_quick_create
:阻止快速创建相关记录——隐藏 创建 “xxx” 下拉菜单项(默认值:false
)no_create_edit
:隐藏 创建并编辑 下拉菜单项(默认值:false
)create_name_field
:在创建相关记录时,如果设置了此选项,则create_name_field
的值将填充为输入值(默认值:name
)。always_reload
:布尔值,默认值为false
。如果为true
,部件将始终执行额外的name_get
来获取其名称值。这适用于重写name_get
方法的情况(请勿这样做)。no_open
:布尔值,默认值为false
。如果设置为true
,点击多对一时不会重定向到记录(在只读模式下)。
<field name="currency_id" options="{'no_create': true, 'no_open': true}" />
- 多对一条码 (
many2one_barcode
) many2one
字段的部件,允许从移动设备(Android/iOS)打开相机以扫描条形码。many2one
字段的特化版本,允许用户使用原生相机扫描条形码。然后使用name_search
搜索该值。如果设置了此部件且用户未使用移动应用程序,它将回退到常规的
many2one`(`Many2OneField
)。支持的字段类型:
many2one
- 多对一头像 (
many2one_avatar
) 此部件仅支持指向继承自
image.mixin
的模型的many2one
字段。在只读模式下,它会在相关记录的display_name
旁边显示其图像。请注意,在这种情况下,display_name
不是可点击的链接。在编辑模式下,它的行为与常规的many2one
完全相同。支持的字段类型:
many2one
- 多对一头像用户 (
many2one_avatar_user
) 此部件是
Many2OneAvatar
的特化版本。单击头像时,会打开与相应用户的聊天窗口。此部件只能设置在指向res.users
模型的many2one
字段上。支持的字段类型:
many2one`(指向 `res.users
)
- 多对一头像员工 (
many2one_avatar_employee
) 与
many2one_avatar_user
类似,但适用于指向hr.employee
的many2one
字段。支持的字段类型:
many2one`(指向 `hr.employee
)
- 多对多 (
many2many
) many2many
字段的默认部件。支持的字段类型:
many2many
属性:
mode
:字符串,默认显示的视图domain
:将数据限制到特定域
选项:
create_text
:允许自定义添加新记录时显示的文本link
:确定是否可以将记录添加到关系中的域(默认值:true
)。unlink
:确定是否可以从关系中移除记录的域(默认值:true
)。
- 多对多二进制文件 (
many2many_binary
) 此部件帮助用户同时上传或删除一个或多个文件。
请注意,此部件特定于
ir.attachment
模型。支持的字段类型:
many2many
选项:
accepted_file_extensions
:用户可以从文件输入对话框中选择的文件扩展名(参见
<input type="file" />
的accept
属性)
- 多对多标签 (
many2many_tags
) 将
many2many
字段显示为标签列表。支持的字段类型:
many2many
选项:
create
:确定是否可以创建新标签的域(默认值:true
)。<field name="category_id" widget="many2many_tags" options="{'create': [['some_other_field', '>', 24]]}" />
color_field
:视图中存在的数字字段的名称。将根据其值选择一种颜色。<field name="category_id" widget="many2many_tags" options="{'color_field': 'color'}" />
no_edit_color
:设置为true
以移除更改标签颜色的可能性(默认值:false
)。<field name="category_id" widget="many2many_tags" options="{'color_field': 'color', 'no_edit_color': true}" />
edit_tags
:设置为true
以通过单击标签来更新与标签相关的记录。(默认值:false
)。<field name="category_id" widget="many2many_tags" options="{'edit_tags': true}" />
- 多对多标签 - 表单视图 (
form.many2many_tags
) many2many_tags
部件针对表单视图的特化版本。它包含一些额外代码,允许编辑标签的颜色。支持的字段类型:
many2many
- 多对多标签 - 看板视图 (
kanban.many2many_tags
) many2many_tags
部件针对看板视图的特化版本。支持的字段类型:
many2many
- 多对多复选框 (
many2many_checkboxes
) 此字段显示一个复选框列表,并允许用户选择选项的子集。请注意,显示值的数量限制为
100
。此限制不可自定义。它仅用于处理极端情况,例如当此部件错误地设置在具有巨大关联模型的字段上时。在这些情况下,列表视图更为合适,因为它支持分页和过滤。支持的字段类型:
many2many
- 一对多 (
one2many
) one2many
字段的默认部件。它通常以子列表视图或子看板视图的形式显示数据。支持的字段类型:
one2many
选项:
create
:确定是否可以创建相关记录的域(默认值:true
)。delete
:确定是否可以删除相关记录的域(默认值:true
)。<field name="turtles" options="{'create': [['some_other_field', '>', 24]]}" />
create_text
:用于自定义“添加”标签/文本的字符串。<field name="turtles" options="{'create_text': 'Add turtle'}" />
- 状态栏 (
statusbar
) 这是表单视图特有的字段。它是许多表单顶部的栏,表示流程并允许选择特定状态。
支持的字段类型:
selection
、many2one
- 引用 (
reference
) reference
字段是选择框(用于模型)和many2one
字段(用于其值)的组合。它允许在任意模型中选择记录。支持的字段类型:
char
、reference
选项:
model_field
:包含可选记录模型的ir.model
名称。当设置此选项时,reference
字段的选择部分不会显示。
部件¶
- 丝带 (
web_ribbon
) 此部件在看板卡片或表单视图的右上角显示一条丝带,例如用于指示已归档的记录。
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger"/>
属性:
title
:丝带中显示的文本。tooltip
:丝带工具提示中显示的文本。bg-class
:设置在丝带上的类名,通常用于定义丝带的颜色。
- 星期天数 (
week_days
) 此部件显示一周中每天的复选框列表,每天对应一个复选框,并允许用户选择选项的子集。
<widget name="week_days" />
客户端动作¶
客户端动作是一个组件,可以作为 Web 客户端中的主要元素显示,占据导航栏下方的所有空间,就像 act_window_action
一样。当您需要一个与现有视图或特定模型无紧密关联的组件时,这非常有用。例如,Discuss 应用程序就是一个客户端动作。
客户端动作是一个根据上下文不同而具有多种含义的术语:
从服务器的角度来看,它是模型 ir_action 的一条记录,包含一个类型为字符的字段 tag。
从 Web 客户端的角度来看,它是注册在动作注册表中与其标签相同键下的 Owl 组件。
每当菜单项与客户端动作关联时,打开它将简单地从服务器获取动作定义,然后在动作注册表中查找其标签以获取组件定义。该组件随后将由动作容器渲染。
添加客户端动作¶
客户端动作是一个控制导航栏下方屏幕部分的组件。定义客户端动作就像创建一个 Owl 组件并将其添加到动作注册表中一样简单。
import { registry } from "@web/core/registry";
class MyClientAction extends Component { ... }
registry.category("actions").add("my-custom-action", ClientAction);
然后,要在 Web 客户端中使用客户端操作,我们需要创建一个客户端操作记录(模型 ir.actions.client
的记录),并设置正确的 tag
属性:
<record id="my_client_action" model="ir.actions.client">
<field name="name">Some Name</field>
<field name="tag">my-custom-action</field>
</record>