资产¶
在 Odoo 中管理资产不像在一些其他应用中那样直接。原因之一是我们有各种情况,其中某些但不是全部的资产是必填的。例如,网络客户端、销售应用、网站甚至移动应用的需求各不相同。此外,某些资产可能较大,但很少使用:在这种情况下,我们可能希望它们按需加载(即懒加载)。
资产类型¶
有三种不同类型的资产:代码(js
文件)、样式(css
或 scss
文件)和模板(xml
文件)。
- 代码
Odoo 支持 三种不同类型的 JavaScript 文件。所有这些文件都会被处理(原生 JS 模块会被转换为 Odoo 模块),然后进行压缩(如果不在
debug=assets
模式 下),并进行合并。最终结果会保存为一个 附件。这些 附件 通常通过<script>
标签在页面的<head>
部分加载(作为静态文件)。- 样式
样式可以通过
css
或 scss 来实现。与 JavaScript 文件类似,这些文件会被处理(scss
文件会被转换为css
),然后被压缩(如果不在debug=assets
模式 下则会进行压缩),并进行合并。最终结果会保存为一个附件。然后通常通过<head>
部分中的<link>
标签加载(作为静态文件)。- 模板
模板(静态
xml
文件)的处理方式不同:它们在需要时直接从文件系统中读取并拼接。每当浏览器加载 Odoo 时,它会调用
/web/webclient/qweb/
控制器以获取 模板。
它很有用的是,要知道在大多数情况下,浏览器只会在第一次加载页面时执行请求。这是因为这些资源都与一个校验和(checksum)相关联,该校验和会被注入到页面源代码中。然后,校验和会被添加到网址中,这意味着可以安全地将缓存头设置为较长的期间。
捆绑包¶
Odoo 资产按 捆绑包 进行分组。每个捆绑包(特定类型的文件路径列表:xml
、js
、css
或 scss
)在 模块清单 中列出。可以使用 glob 语法声明文件,这意味着您可以使用单一行声明多个资产文件。
每个模块的 __manifest__.py
文件中定义了资源包,其中包含一个专用的 assets
键,该键对应一个字典。该字典将资源包名称(键)映射到它们包含的文件列表(值)。其结构如下:
'assets': {
'web.assets_backend': [
'web/static/src/xml/**/*',
],
'web.assets_common': [
'web/static/lib/bootstrap/**/*',
'web/static/src/js/boot.js',
'web/static/src/js/webclient.js',
'web/static/src/xml/webclient.xml',
],
'web.qunit_suite_tests': [
'web/static/src/js/webclient_tests.js',
],
},
以下是一些重要的捆绑包列表,大多数 Odoo 开发人员都需要了解:
web.assets_common
: 此资源包包含大多数对网页客户端、网站以及销售点通用的资源。此资源包应包含 Odoo 框架的底层构建块。请注意,它包含boot.js
文件,该文件定义了 Odoo 模块系统。web.assets_backend
: 此资源包包含与网页客户端相关的代码(特别是网页客户端/动作管理器/视图/静态 XML 模板)web.assets_frontend
: 此资源包包含与公开网站相关的所有内容:电子商务、门户、论坛、博客等。web.qunit_suite_tests
: 所有 JavaScript QUnit 测试代码(测试用例、辅助函数、模拟数据)web.qunit_mobile_suite_tests
: 针对移动设备的 QUnit 测试代码
操作¶
通常,处理资源(assets)比较简单:你只需要将一些新文件添加到常用包中,如 assets_common
或 assets_backend
。但还有其他操作可用于覆盖一些更具体的使用场景。
请注意,所有针对特定资产文件的指令(即 before
、after
、replace
和 remove
)都需要该文件在之前被声明过,无论是通过层级更高的清单文件,还是通过 ir.asset
记录中序列较低的条目。
追加
¶
此操作用于添加一个或多个文件。由于这是最常见的操作,可以通过直接使用文件名来完成:
'web.assets_common': [
'my_addon/static/src/js/**/*',
],
默认情况下,将一个简单的字符串添加到包中会将匹配通配符模式的文件附加到包的末尾。显然,该模式也可以直接是一个单独的文件路径。
前置
¶
在捆绑包的开头添加一个或多个文件。
在需要将某个文件放在捆绑包中其他文件之前时非常有用(例如对于 CSS 文件)。prepend
操作使用以下语法调用:('prepend', <path>)
。
'web.assets_common': [
('prepend', 'my_addon/static/src/css/bootstrap_overridden.scss'),
],
之前
¶
在特定文件之前添加一个或多个文件。
在捆绑包的开头添加文件可能不够精确。可以使用 before
指令将给定的文件*放在目标文件之前*。它通过将正常路径替换为一个 3 元素元组 ('before', <target>, <path>)
来声明。
'web.assets_common': [
('before', 'web/static/src/css/bootstrap_overridden.scss', 'my_addon/static/src/css/bootstrap_overridden.scss'),
],
之后
¶
在特定文件之后添加一个或多个文件。
与 before
相同,但匹配的文件会附加在目标文件的*之后*。它是通过将正常路径替换为一个 3 元素元组 ('after', <target>, <path>)
来声明的。
'web.assets_common': [
('after', 'web/static/src/css/list_view.scss', 'my_addon/static/src/css/list_view.scss'),
],
包含
¶
使用嵌套的捆绑包。
include
指令是一种在其他捆绑包中使用捆绑包的方式,以减小你的清单(manifest)的大小。在 Odoo 中,我们使用子捆绑包(按照惯例,以下划线开头)来批量处理被多个其他捆绑包使用的文件。你可以将子捆绑包指定为一个元组 ('include', <bundle>)
,如下所示:
'web.assets_common': [
('include', 'web._primary_variables'),
],
移除
¶
删除一个或多个文件。
在某些情况下,您可能需要从一个包中移除一个或多个文件。这可以通过使用 remove
指令来实现,方法是指定一个元组 ('remove', <target>)
:
'web.assets_common': [
('remove', 'web/static/src/js/boot.js'),
],
替换
¶
用一个或多个文件替换资产文件。
假设某个资产不仅需要被移除,你还希望在同一位置插入该资产的新版本。这可以通过 replace
指令实现,使用一个 3 元素元组 ('replace', <target>, <path>)
:
'web.assets_common': [
('replace', 'web/static/src/js/boot.js', 'my_addon/static/src/js/boot.js'),
],
加载顺序¶
资产加载的顺序有时是关键的,并且必须是确定性的,尤其是在样式表优先级和设置脚本方面。Odoo 中的资产处理方式如下:
当调用资产包时(例如
t-call-assets="web.assets_common"
),会生成一个空的资产列表所有类型为
ir.asset
的记录都会根据捆绑包进行筛选,并按序列号排序。然后,所有序列号严格小于 16 的记录都会被处理,并应用到当前的资产列表中。所有声明了该捆绑包资产的模块在其清单中会将其资产操作应用到此列表。这是按照模块依赖顺序进行的(例如,
web
的资产会在website
之前处理)。如果某个指令尝试添加已存在于列表中的文件,则对该文件不执行任何操作。换句话说,列表中只保留第一个出现的文件。剩下的
ir.asset
记录(序列大于或等于 16 的记录)也会被处理并应用。
在清单中声明的资产可能需要按特定顺序加载,例如:jquery.js
在加载 lib 文件夹时必须在所有其他 jquery 脚本之前加载。一种解决方案是创建一个 ir.asset 记录,并设置较低的序列或使用“prepend”指令,但还有另一种更简单的方法可以实现这一点。
由于资产列表中每个文件路径的唯一性得到了保证,您可以在包含它的通配符(glob)之前提及任何特定文件。这样,该文件将在所有被通配符包含的其他文件之前出现在列表中。
'web.assets_common': [
'my_addon/static/lib/jquery/jquery.js',
'my_addon/static/lib/jquery/**/*',
],
注解
一个模块 b 如果要移除或替换模块 a 中声明的资源,必须依赖于模块 a。尝试对尚未声明的资源进行操作会导致错误。
延迟加载¶
有时动态加载文件和/或资产包会很有用,例如在需要时才加载一个库。为此,Odoo 框架提供了一些辅助函数,位于 @web/core/assets
中。
await loadAssets({
jsLibs: ["/web/static/lib/stacktracejs/stacktrace.js"],
});
- loadAssets(assets)¶
- 参数
assets (
Object()
) – 各种应加载的资源的描述
- 返回
Promise<void>
加载由
assets
参数描述的资源。它是一个可能包含以下键的对象:键
类型
描述
js库
字符串[]
JavaScript 文件的 URL 列表
cssLibs
字符串[]
CSS 文件的 URL 列表
- useAssets(assets)¶
- 参数
assets (
Object()
) – 各种应加载的资源的描述
此钩子在组件需要在其
onWillStart
方法中加载一些资源时非常有用。它内部调用了loadAssets
。
资产模型(ir.asset
)¶
在大多数情况下,清单中声明的资源已经足够使用。然而,为了获得更大的灵活性,框架还支持在数据库中声明的动态资源。
这是通过创建 ir.asset
记录来实现的。这些记录将被处理,就好像它们出现在模块清单中一样,它们提供的表达能力与清单中的对应项相同。
- class odoo.addons.base.models.ir_asset.IrAsset(env: api.Environment, ids: tuple[IdType, ...], prefetch_ids: Reversible[IdType])[源代码]¶
This model contributes to two things:
1. It provides a function returning a list of all file paths declared in a given list of addons (see _get_addon_paths);
2. It allows to create ‘ir.asset’ records to add additional directives to certain bundles.
名称
资产记录的名称(用于标识)。
捆绑包
资产将被应用的包。
指令
(默认=追加
)此字段确定
path`(以及需要时的 `target
)将如何被解释。以下是可用指令及其所需参数的列表:追加:
path
prepend:
路径
before:
target
,path
之后:
目标
,路径
包含: `path`(被解释为一个 捆绑包名称)
移除:
路径
(被解释为要移除的 目标资产)替换:
目标
,路径
路径
一个定义以下之一的字符串:
一个指向模块文件系统中资产文件的 相对路径;
一个 通配符模式,用于将资产文件集匹配到插件文件系统中的文件;
一个指向附件或外部资产文件的 网址;
一个 捆绑包名称,在使用
include
指令时。
目标
目标文件,用于在包中指定位置。只能与指令
replace
、before
和after
一起使用。激活`(默认值为 `True
)是否激活记录
序列`(默认= `16
)资产记录的加载顺序(升序)。序列值小于 16 表示该资产将在清单中声明的资产之前被处理。