资源¶
在 Odoo 中管理资源并不像在某些其他应用中那么简单。原因之一是,我们有各种各样只需要部分(而非全部)资源的场景。例如,网页客户端、销售点应用、网站甚至移动应用的需求各不相同。此外,有些资源可能很大,但很少需要使用:在这种情况下,我们可能希望它们被 懒加载(按需加载)。
资源类型¶
共有三种不同的资源类型:代码(js 文件)、样式(css 或 scss 文件)和模板(xml 文件)。
- 代码
Odoo 支持 三种不同的 JavaScript 文件。所有这些文件都会先被处理(原生 JS 模块会被转换为 odoo 模块),然后进行压缩(如果不在
debug=assets模式 下),再进行拼接。结果随后会保存为文件附件。这些文件附件通常通过页面<head>部分中的<script>标签(作为静态文件)加载。- 样式
样式可以使用
css或 scss 编写。与 JavaScript 文件一样,这些文件会先被处理(scss文件会被转换为css),然后进行压缩(同样,如果不在debug=assets模式 下),再进行拼接。结果随后会保存为文件附件。它们通常通过页面<head>部分中的<link>标签(作为静态文件)加载。- 模板
模板(静态
xml文件)的处理方式有所不同:它们只是在需要时从文件系统中读取,然后进行拼接。每当浏览器加载 odoo 时,它都会调用
/web/webclient/qweb/控制器来获取 模板。
了解这一点很有用:在大多数情况下,浏览器只在第一次加载页面时执行请求。这是因为每个资源都关联着一个校验和,该校验和会注入到页面源码中。校验和随后会添加到 url 中,这意味着可以安全地将缓存头设置为较长的时间。
资源包¶
Odoo 资源按 bundles (包)分组。每个包(特定类型(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.qunit_suite_tests': [
'web/static/src/js/webclient_tests.js',
],
},
以下是一些大多数 odoo 开发者都需要了解的重要资源包的列表:
web.assets_common:该包包含网页客户端、网站以及销售点共有的大部分资源。它应当包含 odoo 框架的底层构建块。请注意,它包含定义了 odoo 模块系统的boot.js文件。web.assets_backend:该包包含网页客户端特有的代码(主要是网页客户端/动作管理器/视图/静态 XML 模板)web.assets_frontend:该包包含公共网站特有的一切内容:电子商务、门户、论坛、博客等web.qunit_suite_tests:所有 JavaScript qunit 测试代码(测试、辅助工具、模拟)web.qunit_mobile_suite_tests:移动端特有的 qunit 测试代码
操作¶
通常,处理资源很简单:您只需将一些新文件添加到 assets_common 或 assets_backend 等常用包中即可。但还有一些其他操作可用于应对一些更具体的用例。
请注意,所有针对某个资源文件进行操作的指令(即 before、after、replace 和 remove)都要求该文件事先已被声明,要么在层级结构中上层的清单中声明,要么在序号较小的 ir.asset 记录中声明。
append¶
该操作添加一个或多个文件。由于它是最常用的操作,可以直接使用文件名来完成:
'web.assets_common': [
'my_addon/static/src/js/**/*',
],
默认情况下,向包中添加一个简单字符串会将匹配 glob 模式的文件追加到该包的末尾。显然,该模式也可以直接是单个文件路径。
prepend¶
在包的开头添加一个或多个文件。
当您需要将某个文件放在包中其他文件之前时(例如 css 文件),此操作很有用。prepend 操作使用以下语法调用:('prepend', <path>)。
'web.assets_common': [
('prepend', 'my_addon/static/src/css/bootstrap_overridden.scss'),
],
before¶
在特定文件之前添加一个或多个文件。
将文件前置到包的开头可能不够精确。before 指令可用于将给定文件添加到目标文件的紧 前面。它通过用一个 3 元素元组 ('before', <target>, <path>) 替代普通路径来声明。
'web.assets_common': [
('before', 'web/static/src/css/bootstrap_overridden.scss', 'my_addon/static/src/css/bootstrap_overridden.scss'),
],
after¶
在特定文件之后添加一个或多个文件。
与 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¶
使用嵌套的资源包。
include 指令是一种在其他包中使用某个包的方法,可以最大限度地缩小清单的体积。在 Odoo 中,我们使用子包(按照惯例以下划线为前缀)来归集在多个其他包中使用的文件。然后,您可以像这样将子包指定为 ('include', <bundle>) 对:
'web.assets_common': [
('include', 'web._primary_variables'),
],
remove¶
删除一个或多个文件。
在某些情况下,您可能希望从包中删除一个或多个文件。这可以通过 remove 指令并指定 ('remove', <target>) 对来完成:
'web.assets_common': [
('remove', 'web/static/src/js/boot.js'),
],
replace¶
用一个或多个文件替换某个资源文件。
假设不仅需要删除某个资源,还想在完全相同的位置插入您自己该资源的新版本。这可以通过 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 的记录)随后也会被处理并应用。
在清单中声明的资源可能需要按特定的顺序加载,例如在加载 lib 文件夹时,jquery.js 必须在所有其他 jquery 脚本之前加载。一种解决方案是创建一个序号更小的 ir.asset 记录或使用 ‘prepend’ 指令,但还有一种更简单的方法。
由于资源列表中每个文件路径的唯一性是有保证的,您可以在包含该文件的 glob 之前提及任何特定文件。这样,该文件就会出现在列表中 glob 所包含的所有其他文件之前。
'web.assets_common': [
'my_addon/static/lib/jquery/jquery.js',
'my_addon/static/lib/jquery/**/*',
],
Note
删除/替换模块 a 中所声明资源的模块 b 必须依赖于模块 a。试图操作尚未声明的资源将导致错误。
懒加载¶
有时动态加载文件和/或资源包会很有用,例如只在需要时才加载某个库。为此,Odoo 框架提供了一些辅助函数,位于 @web/core/assets 中。
await loadAssets({
jsLibs: ["/web/static/lib/stacktracejs/stacktrace.js"],
});
- loadAssets(assets)¶
- 参数
assets (
Object()) – a description of various assets that should be loaded
- 返回
Promise<void>
加载由
assets参数描述的资源。它是一个对象,可以包含以下键:键
类型
说明
jsLibsstring[]JavaScript 文件的 URL 列表
cssLibsstring[]CSS 文件的 URL 列表
- useAssets(assets)¶
- 参数
assets (
Object()) – a description of various assets that should be loaded
当组件需要在
onWillStart方法中加载一些资源时,该钩子非常有用。它内部会调用loadAssets。
资源模型(ir.asset)¶
在大多数情况下,清单中声明的资源已足够使用。然而,为了提供更大的灵活性,该框架还支持在数据库中声明的动态资源。
这是通过创建 ir.asset 记录来实现的。这些记录的处理方式就如同在模块清单中找到的一样,并且它们提供了与清单中的对应项同等的表达能力。
name资源记录的名称(用于标识)。
bundle应用该资源的包。
directive(默认=append)该字段决定了
path(以及必要时target)将如何被解释。以下是可用指令及其所需参数的列表:append:
pathprepend:
pathbefore:
target,pathafter:
target,pathinclude:
path(解释为 包名)remove:
path(解释为要移除的 目标资源)replace:
target,path
path一个字符串,定义以下之一:
指向插件文件系统中某个资源文件的 相对路径;
匹配插件文件系统中一组资源文件的 glob 模式;
指向某个附件或外部资源文件的 URL;
一个 包名,当使用
include指令时。
target用于指定包中位置的目标文件。只能与
replace、before和after指令一起使用。active(默认=True)该记录是否处于激活状态
sequence(默认=16)资源记录的加载顺序(升序)。序列低于 16 表示该资源将在清单中声明的那些资源 之前 被处理。