数据文件(Data Files)

Odoo 是高度数据驱动的,因此模块定义的一个重要部分是其管理的各种记录的定义:用户界面(菜单和视图)、安全性(访问权限和记录规则)、报表以及普通数据都是通过记录定义的。

结构

在 Odoo 中定义数据的主要方式是通过 XML 数据文件:XML 数据文件的大致结构如下:

  • 根元素 odoo 内可以包含任意数量的操作元素

<?xml version="1.0" encoding="UTF-8"?>
<!-- the root elements of the data file -->
<odoo>
    <operation/>
    ...
</odoo>

数据文件按顺序执行,操作只能引用之前定义的操作结果

注解

如果数据文件的内容仅需应用一次,可以将 odoo 标志 noupdate 设置为 1。如果文件中的部分数据仅需应用一次,可以将这部分内容放置在 <data noupdate=”1”> 域中。

<odoo>
    <data noupdate="1">
        <!-- Only loaded when installing the module (odoo-bin -i module) -->
        <operation/>
    </data>

    <!-- (Re)Loaded at install and update (odoo-bin -i/-u) -->
    <operation/>
</odoo>

核心操作

record

record 用于适当地定义或更新数据库记录,它具有以下属性:

model (必填)

要创建(或更新)的模型名称

id

此记录的 external identifier 。强烈建议提供一个

  • 对于记录创建,允许后续定义修改或引用此记录

  • 对于记录修改,指定要修改的记录

context

创建记录时使用的上下文

forcecreate

在更新模式下,如果记录不存在,是否应创建该记录

需要一个 外部标识符,默认为 True。

field

每个记录可以由 field 标签组成,定义在创建记录时要设置的值。没有 field 的 record 将使用所有默认值(创建)或不执行任何操作(更新)。

一个 field 具有一个强制的 name 属性,即要设置的字段名称,并有多种方法来定义值本身:

无

如果没有为字段提供值,则会在字段上隐式设置 False 。可用于清除字段或避免使用字段的默认值。

search

对于 关系字段 ,应该是字段模型上的 域 。

将评估域,使用它搜索字段模型并将搜索结果设置为字段的值。如果字段是 Many2one ,则只会使用第一个结果。

ref

如果提供了 ref 属性,则其值必须是有效的 external identifier ,它将被查找并设置为字段的值。

主要用于 Many2one 和 Reference 字段

type

如果提供了 type 属性,它将用于解释和转换字段的内容。字段的内容可以通过外部文件使用 file 属性提供,或者通过节点主体提供。

可用类型包括:

xml, html

提取 field 的子元素作为单个文档,评估任何以 %(external_id)s 形式指定的 external identifier 。可以使用 %% 输出实际的 % 符号。

file

确保字段内容是当前模型中的有效文件路径,并将 {module},{path} 对保存为字段值

char

直接将字段内容设置为字段值,不做任何更改

base64

对字段内容进行 base64 编码,结合 file 属性可用于加载图像数据到附件中

int

将字段内容转换为整数并设置为字段值

float

将字段内容转换为浮点数并设置为字段值

list, tuple

应包含任意数量具有与 field 相同属性的 value 元素,每个元素解析为生成的元组或列表的一项,生成的集合被设置为字段值

eval

对于前述方法不适用的情况,eval 属性会简单地评估所提供的任何 Python 表达式,并将其结果设置为字段值。

评估上下文包含多个模块( time 、 datetime 、 timedelta 、 relativedelta )、一个解析 external identifier 的函数( ref ),以及当前字段对应的模型对象(如果适用,则为 obj )。

delete

delete 标签可以删除先前定义的任意数量的记录。它具有以下属性:

model (必填)

指定记录应被删除的模型

id

要删除的记录的 external identifier

search

用于查找要删除的模型记录的 域

id 和 search 是互斥的

function

function 标签调用模型上的方法,并提供参数。它有两个必填参数: model 和 name ,分别指定要调用的模型和方法名称。

可以使用 eval (应评估为调用方法的参数序列)或 value 元素(参见 list 值)来提供参数。

<odoo>
    <data noupdate="1">
        <record id="partner_1" model="res.partner">
            <field name="name">Odude</field>
        </record>

        <function model="res.partner" name="send_inscription_notice"
            eval="[[ref('partner_1'), ref('partner_2')]]"/>

        <function model="res.users" name="send_vip_inscription_notice">
            <function eval="[[('vip','=',True)]]" model="res.partner" name="search"/>
        </function>
    </data>

    <record id="model_form_view" model="ir.ui.view">
        ...
    </record>
</odoo>

快捷方式

由于 Odoo 的一些重要结构化模型复杂且涉及较多内容,数据文件提供了使用 record 标签 定义它们的更简短替代方案:

template

创建一个 QWeb 视图 ,仅需视图的 arch 部分,并允许一些 可选 属性:

id

视图的 external identifier

name、inherit_id、priority

与 ir.ui.view 上的对应字段相同(注意: inherit_id 应为 external identifier )

primary

如果设置为 True 并与 inherit_id 结合,将视图定义为主视图

groups

组 external identifier 的逗号分隔列表

active

指示视图是否处于激活状态。若视图未激活,其 XPath 规则不会被应用,因此这一属性主要与带有 inherit_id 的视图相关。

注解

直接在 <template> 节点上定义 active 值有一处微妙之处:它仅在创建记录时被考虑。此后的更新中,视图会被更新,但其 active 状态不会随之改变。

asset

创建一项 资产(asset)。

Example

<asset id="website_something.some_style_asset" name="Some style asset" active="False">
    <bundle>web.assets_frontend</bundle>
    <path>website_something/static/src/some_style.scss</path>
</asset>

属性

id

该资产的 外部标识符

name

与 ir.asset 上的对应字段相同

active (可选)

指示该资产是否处于激活状态

注解

与 <template> 一样,直接在 <asset> 节点上定义 active 值也有一处微妙之处:它仅在创建记录时被考虑。此后的更新中,资产会被更新,但其 active 状态不会随之改变。

子元素

<bundle> 与 <path>

定义 ir.asset 上对应字段时所需(directive 字段可通过 <bundle> 子元素上的 directive 属性控制)

<field> (可选)

与普通 <record> 一样,可按需定义更多字段值

CSV 数据文件

XML 数据文件灵活且自描述,但在批量创建大量同一模型的简单记录时非常冗长。

在这种情况下,数据文件也可以使用 csv ,这通常适用于 访问权限 :

  • 文件名为 model_name.csv

  • 第一行列出要写入的字段,其中特殊字段 id 用于 external identifier (用于创建或更新)

  • 之后的每一行都会创建一条新记录

以下是定义国家州数据文件 res.country.state.csv 的前几行

"id","country_id:id","name","code"
state_au_1,au,"Australian Capital Territory","ACT"
state_au_2,au,"New South Wales","NSW"
state_au_3,au,"Northern Territory","NT"
state_au_4,au,"Queensland","QLD"
state_au_5,au,"South Australia","SA"
state_au_6,au,"Tasmania","TAS"
state_au_7,au,"Victoria","VIC"
state_au_8,au,"Western Australia","WA"
state_us_1,us,"Alabama","AL"
state_us_2,us,"Alaska","AK"
state_us_3,us,"Arizona","AZ"
state_us_4,us,"Arkansas","AR"
state_us_5,us,"California","CA"
state_us_6,us,"Colorado","CO"

以更易读的格式呈现:

ID

country_id:id

名称

代码

state_au_1

澳大利亚

澳大利亚首都地区

ACT

state_au_2

澳大利亚

新南威尔士州

NSW

state_au_3

澳大利亚

北领地

NT

state_au_4

澳大利亚

昆士兰州

QLD

state_au_5

澳大利亚

南澳大利亚州

SA

state_au_6

澳大利亚

塔斯马尼亚州

TAS

state_au_7

澳大利亚

维多利亚州

VIC

state_au_8

澳大利亚

西澳大利亚州

WA

state_us_1

美国

阿拉巴马州

AL

state_us_2

美国

阿拉斯加州

阿拉斯加

美国州代码_3

美国

亚利桑那州

AZ

state_us_4

美国

阿肯色州

AR

state_us_5

美国

加利福尼亚州

CA

state_us_6

美国

科罗拉多州

CO

对于每一行(记录):

  • 第一列是要创建或更新的记录的 external identifier

  • 第二列是要链接的国家对象的 external identifier (国家对象必须事先定义)

  • 第三列是 res.country.state 的 name 字段

  • 第四列是 res.country.state 的 code 字段