资源

在 Odoo 中管理资源不像在其他一些应用程序中那样简单直接。原因之一是我们有多种情况,其中某些资源是必需的,但并非所有资源都是如此。例如,Web 客户端、销售点应用程序、网站甚至移动应用程序的需求各不相同。此外,某些资源可能很大,但很少需要:在这种情况下,我们可能希望它们能够 按需懒加载

资源类型

有三种不同的资源类型:代码(js 文件)、样式(cssscss 文件)和模板(xml 文件)。

代码

Odoo 支持 三种不同类型的 JavaScript 文件。所有这些文件都会被处理(原生 JS 模块会被转换为 Odoo 模块),然后进行压缩(如果不是在 debug=assets 模式下),最后合并。结果会保存为文件附件。这些文件附件通常通过页面 <head> 部分的 <script> 标签加载(作为静态文件)。

样式

样式可以通过 cssscss 来实现。与 JavaScript 文件类似,这些文件会被处理(scss 文件会被转换为 css),然后进行压缩(同样,如果不是在 debug=assets 模式下),最后合并。结果会保存为文件附件,并通过页面 <head> 部分的 <link> 标签加载(作为静态文件)。

模板

模板(静态 xml 文件)的处理方式有所不同:它们会在需要时从文件系统中读取并合并。

每当浏览器加载 Odoo 时,它会调用 /web/webclient/qweb/ 控制器来获取 模板

需要了解的是,在大多数情况下,浏览器只会在首次加载页面时发出请求。这是因为每个资源都与一个校验和相关联,该值会被注入到页面源码中。校验和随后会被添加到 URL 中,这意味着可以安全地将缓存头设置为较长的期限。

资源包

Odoo 资源按 资源包 分组。每个资源包(特定类型的文件路径列表:xmljscssscss)都会列在 模块清单 中。文件可以通过 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:此资源包包含 Web 客户端、网站以及销售点共用的大部分资源。它应该包含 Odoo 框架的底层构建块。请注意,它包含 boot.js 文件,该文件定义了 Odoo 模块系统。

  • web.assets_backend:此资源包包含特定于 Web 客户端的代码(特别是 Web 客户端/操作管理器/视图/静态 XML 模板)。

  • web.assets_frontend:此资源包包含所有与公共网站相关的特定内容:电子商务、门户、论坛、博客等。

  • web.qunit_suite_tests:所有 JavaScript QUnit 测试代码(测试、辅助工具、模拟对象)。

  • web.qunit_mobile_suite_tests:移动设备专用的 QUnit 测试代码

操作

通常,处理资源非常简单:只需将一些新文件添加到常用资源包(如 assets_commonassets_backend)中即可。但还有其他操作可用于满足某些更具体的需求。

请注意,所有针对特定资源文件的指令(如 beforeafterreplaceremove)都需要该文件事先声明,要么在更高层级的清单文件中声明,要么在具有较低序列号的 ir.asset 记录中声明。

append

此操作用于添加一个或多个文件。由于这是最常见的操作,因此可以通过直接使用文件名来完成:

'web.assets_common': [
    'my_addon/static/src/js/**/*',
],

默认情况下,向资源包中添加一个简单的字符串会将匹配通配符模式的文件追加到资源包的末尾。显然,该模式也可以直接是单个文件路径。

prepend

在资源包的开头添加一个或多个文件。

当需要将某个文件放在资源包中其他文件之前时非常有用(例如 CSS 文件)。prepend 操作的调用语法为:('prepend', <path>)

'web.assets_common': [
    ('prepend', 'my_addon/static/src/css/bootstrap_overridden.scss'),
],

before

在特定文件之前添加一个或多个文件。

在资源包开头添加文件可能不够精确。可以使用 before 指令将指定文件添加到目标文件的 之前。它通过将普通路径替换为三元组 ('before', <target>, <path>) 来声明。

'web.assets_common': [
    ('before', 'web/static/src/css/bootstrap_overridden.scss', 'my_addon/static/src/css/bootstrap_overridden.scss'),
],

after

在特定文件之后添加一个或多个文件。

before 类似,只是匹配的文件会被追加到目标文件的 之后。它通过将普通路径替换为三元组 ('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 指令完成,使用三元组 ('replace', <target>, <path>)

'web.assets_common': [
    ('replace', 'web/static/src/js/boot.js', 'my_addon/static/src/js/boot.js'),
],

加载顺序

资源的加载顺序有时至关重要且必须确定,尤其对于样式表优先级和初始化脚本而言。Odoo 中的资源按以下方式处理:

  1. 当调用一个资源包(例如 t-call-assets="web.assets_common")时,会生成一个空的资源列表

  2. 获取与该资源包匹配的所有类型为 ir.asset 的记录,并按序列号排序。然后,处理所有序列号严格小于 16 的记录,并将其应用于当前的资源列表。

  3. 所有在清单文件中声明了资源的模块都会将其资源操作应用到此列表中。这是按照模块依赖顺序完成的(例如,web 的资源会在 website 之前处理)。如果某指令尝试添加一个已存在于列表中的文件,则不会对该文件执行任何操作。换句话说,只有文件的第一次出现会被保留在列表中。

  4. 其余的 ir.asset 记录(序列号大于或等于 16 的记录)随后也会被处理并应用。

清单文件中声明的资源可能需要以特定顺序加载,例如,在加载 lib 文件夹时,必须先加载 jquery.js,然后再加载其他 jQuery 脚本。一种解决方案是创建一个序列号较低的 ir.asset 记录或使用 ‘prepend’ 指令,但还有另一种更简单的方法可以实现这一点。

由于资产列表中每个文件路径的唯一性是有保证的,因此您可以在通配符之前提到任何特定文件。这样,该文件将出现在通配符包含的所有其他文件之前。

'web.assets_common': [
    'my_addon/static/lib/jquery/jquery.js',
    'my_addon/static/lib/jquery/**/*',
],

注解

模块 b 如果要移除或替换模块 a 中声明的资源,则必须依赖于它。尝试对尚未声明的资源进行操作会导致错误。

懒加载

有时动态加载文件和/或资源包会很有用,例如仅在需要时加载某个库。为此,Odoo 框架提供了一些辅助函数,位于 @web/core/assets 中。

await loadAssets({
    jsLibs: ["/web/static/lib/stacktracejs/stacktrace.js"],
});
loadAssets(assets)
参数
  • assets (Object()) – 应加载的各种资源的描述

返回

Promise<void>

加载由 assets 参数描述的资源。它是一个对象,可能包含以下键:

类型

描述

jsLibs

string[]

JavaScript 文件的 URL 列表

cssLibs

string[]

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])[源代码]

此模型实现了两个功能:

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.

name

资产记录的名称(用于标识目的)。

bundle

应用资产的资源包。

指令`(默认值为 `append

此字段决定如何解释 path`(以及需要时的 `target)。以下是可用指令及其所需参数的列表:

  • appendpath

  • prependpath

  • beforetargetpath

  • aftertargetpath

  • includepath (被解释为一个 资源包名称

  • remove: path (interpreted as a target asset to remove)

  • replacetargetpath

路径

一个字符串,定义以下内容之一:

  • 插件文件系统中资源文件的 相对路径

  • 插件文件系统中一组资源文件的 通配符模式

  • 指向附件或外部资源文件的 URL

  • 当使用 include 指令时的 资源包名称

目标

用于指定资源包中位置的目标文件。只能与指令 replacebeforeafter 一起使用。

启用状态`(默认值为 `True

记录是否处于活动状态

顺序`(默认值为 `16

资源记录的加载顺序(升序)。小于 16 的顺序意味着该资源将在清单文件中声明的资源之前被处理。