Chapter 4 Data Serialization and Module Data 数据序列化以及模块数据


Most Odoo configurations, from user interfaces to security rules, are actually
data records stored in internal Odoo tables. The XML and CSV files found in modules are not used to run Odoo applications. They are just a means to load those configurations into the database tables.

从用户界面到安全规则,大多数的Odoo配置,实际数据记录都是存储在Odoo表的内部。模块中发现的XML和CSV并不用来运行Odoo应用。它们仅表示将文件中的配置载入到数据库表中。

Because of this, an important part of Odoo modules is about representing (serializing) that data into files so that it can be later loaded into a database.

因此,Odoo模块中很重要的一部分是关于数据到文件的表现(序列化),所以这些数据文件可以稍晚时候再载入到数据库。

Modules can also have initial and demonstration (fixture) data. Data serialization allows adding that to our modules. Additionally, understanding Odoo data serialization formats is important in order to export and import data in the context of a project implementation.

模块也可以拥有初始和说明(固定的)数据。数据序列化允许对模块添加这些数据。此外,理解Odoo的数据序列化格式在一个项目实现的上下文中导入和导出数据显得特别重要。

Before we go into practical cases, we will first explore the external identifier concept, which is the key to Odoo data serialization.

在我们开始实际演练之前,我们首先来浏览外部标识符的概念,这也是Odoo数据序列化的关键所在。

Understanding external identifiers 理解外部标识符

All records in the Odoo database have a unique identifier, the id field.

在Odoo数据中的所有记录都拥有一个唯一的标识符,id字段。

It is a sequential number automatically assigned by the database. However, this automatic identifier can be a challenge when loading interrelated data: how can we reference a related record if we can’t know beforehand what database ID will be assigned to it?

这是一个由数据库自动赋值的序列编号。不过,在载入相互关联的数据时这个自动生成的标识符就是个挑战:在我们不能预先知道什么数据库ID被分配的情况下,我们如何在我们不能预先知道分配到关联数据的数据库ID的情况下引用关联记录?

Odoo’s answer to this is the external identifier. External identifiers solve this problem by assigning named identiers to the data records to be loaded. A named identifier can be used by any other piece of record data to reference it later on. Odoo will take care of translating these identifier names into the actual database IDs assigned to them.

Odoo对于这种情况的解决方法是使用外部标识符。外部标识符依靠对需要载入的数据记录赋予命名标识符来解决这个问题。命名的标识符可以被任意其他记录数据在稍后使用。Odoo会将这些标识符名称翻译到实际的数据ID

The mechanism behind this is quite simple: Odoo keeps a table with the mapping between the named External IDs and their corresponding numeric database IDs. That is the ir.model.data model.

这背后的机制也相当简单:Odoo使用被命名的外部ID及其对应的数据库数字ID之间映射保存表。这就是ir.model.data模型。

To inspect the existing mappings, go to the Technical section of the Settings menu, and select the Sequences & Identifiers | External Identifiers menu item.

检查现存的映射,可以找到“设置”菜单的“技术”部分,然后选择“序列与标识符|外部标识符”菜单选项。

For example, if we visit the External Identifiers list and filter it by the todo_app module, we will see the external identifiers generated by the module created previously.

例如,如果我们访问“外部标识符”列表,然后输入todo_app进行过滤,我们可以看见模块在之前创建的外部标识符。

img:omit

You can see that the external identi ers have a Complete ID label. This is composed of the module name and the identifier name joined by a dot, for example, todo_app.action_todo_task.

你可以看到外部标识符拥有一个“完整ID”标签。

Since only the Complete ID is required to be unique, the module name ends up acting as a namespace for identi ers. This means that the same named identi er can be repeated in different modules, and we don’t need to worry about identi ers in our module colliding with identi ers in other modules.

At the top of the list, you can see the todo_app.action_todo_task ID. This is the menu action we created for the module, which is also referenced in the corresponding menu item. By clicking on it, you can open a form with its details: the action_todo_task in the todo_app module maps to a specific record ID in the ir.actions.act_window model.

在列表的顶部,你可以看到 todo_app.action_todo_taskID。这是一个我们为模块创建的菜单动作,它也被应用到了对应的菜单项目中。通过点击这个菜单,你可以打开一个拥有自身细节的表单:todo_app模块中的action_todo_task被映射到了ir.actions.act_window模型中的指定记录ID。

img:omit

Besides providing a way for records to easily reference other records, External IDs also allow avoiding data duplication on repeated imports. If the External ID is already present, the existing record will be updated, instead of creating a new record. This is why, on subsequent module upgrades, previously loaded records are updated instead of being duplicated.

除了为记录提供了简单的引用其它记录值一种办法之外,外部ID也能够在重复导入时避免数据的重复。如果外部ID已经存在,那么存在的记录将被更新,而不是另外创建一个新纪录。

Finding External IDs 查找外部ID

When preparing configuration and demonstration data files for modules, we frequently need to look up existing External IDs that are needed for references.

在准备模块的配置和演示文件时,我们经常需要查找需要引用到的现有外部ID。

We can use the External Identifiers menu shown earlier, but the Developer Menu can provide a more convenient method for that. As you may recall from Chapter 1, Getting Started with Odoo Development, the Developer Menu is activated in the About Odoo option, and then, it is available at the top-left corner of the web client view.

我们可以使用前面出现过的外部标识符菜单,但是Developer Menu提供了一种更为方便的方式。

To find the External ID for a data record, on the corresponding Form view, select the View Metadata option from the Developer Menu. This will display a dialog with the record’s database ID and External ID (also known as XML ID).

要查找数据记录的外部ID,

As an example, to look up the Demo user ID, we can navigate to its Form view (Settings | Users) and select the View Metadata option, after which we will be shown this:

例如,查询Demo用户的ID,我们可以

img:omit

To find the External ID for view elements, such as form, tree, search, and action, the Developer Menu is also a good help. For that, use its Manage Views option or open the information for the desired view using the Edit options, and then select their View Metadata option.

要查找视图元素的外部ID,比如表单、树形、搜索和动作,Developer Menu也可以用到。为此,我们使用Manage Views的Manage Views选项,或者

Exporting and importing data 导出和导入数据

We will start exploring how data export and import work in Odoo, and from there, we will move on to the more technical details.

Exporting data 导出数据

Data export is a standard feature available in any List view. To use it, we must first select the rows to export by selecting the corresponding checkboxes on the far left, and then select the Export option from the More button.

数据导出是在任何一个列表视图中有存在的标准功能。要使用它,首先,我们必须选择

Here is an example, using the recently created to-do tasks:

下面是一个例子,使用最近创建的to-do tasks:

img:omit

The Export option takes us to a dialog form, where we can choose what to export. The Import Compatible Export option makes sure that the exported file can be imported back to Odoo. We will need to use this.

“导出”选项把我们带到一个对话表单,这里我们可以选择希望导入的内容。

The export format can be CSV or Excel. We will prefer CSV file to get a better understanding of the export format. Next, we should pick the columns we want to export and click on the Export To File button. This will start the download of a file with the exported data.

导出格式可以是CSV或者EXcel。我们倾向于选择CSV文件以更好理解导出的格式。接下来,我们应该选择我们希望导入的列,然后点击“导出到文件”按钮。这样做会下载一个含有导出数据的文件。

img:omit

If we follow these instructions and select the fields shown in the preceding screenshot, we should end up with a CSV text file similar to this:

如果我们依照这些命令,然后选择之前截图中出现的字段,我们应该向下面这样结束一个CSV文本文件:

  1. "id","name","user_id/id","date_deadline","is_done"
  2. "__export__.todo_task_1","Install Odoo","base.user_root","2015-01-
  3. 30","True"
  4. "__export__.todo_task_2","Create dev database","base.user_
  5. root","","False"

Notice that Odoo automatically exported an additional id column. This is an External ID that is automatically generated for each record. These generated External IDs use __export__ in place of an actual module name. New identi ers are only assigned to records that don’t already have one, and from there on, they are kept bound to the same record. This means that subsequent exports will preserve the same External IDs.

注意Odoo可以自动地导出外部id列。这是一个为每个记录自动生成的ID。这些外部ID

Importing data 导入数据

First we have to make sure the import feature is enabled. This is done in the Settings menu, Configuration | General Settings option. Under the Import / Export topic, make sure the Allow users to import data from CSV files checkbox is enabled.

首先,我们必须确保导入功能启用。你可以运用设置菜单中的“配置|通用设置”选项来完成这项操作。

With this option enabled, the List views show an Import option next to the Create button at the top of the list.

当启用这个选项时,列表视图显示一个“导入”选项,旁边是一个在列表顶部的“创建”按钮。

Let’s perform a mass edit on our to-do data: open in a spreadsheet or a text editor the CSV file we just downloaded, then change a few values and add some new rows.

让我们来对to-do数据执行批量编辑:在电子表格或者文本编辑器中打开我们刚才下载的CSV文件,然后改版几个值,再添加几个新行。

As mentioned before, the first id column provides a unique identifier for each row allowing already existing records to be updated instead of duplicated when we import the data back to Odoo. For new rows we may add to the CSV le, the id should be left blank, and a new record will be created for them.

就像之前说的那样,第一个id列为每一个行都提供了唯一标识符,以允许已经存在的记录可以被更新,而不是被复制,

After saving the changes on the CSV file, click on the Import option (next to the Create button) and we will be presented with the import assistant. There we should select the CSV file location on disk and click on Validate to check its format for correctness. Since the file to import is based on an Odoo export, there is a good chance it will be valid.

当保存对CSV文件变更之后,点击“导入”选项(靠近“创建”按钮),我们

img:omit

Now we can click on Import and there you go: our modifications and new records should have been loaded into Odoo.

现在,我们可以点击“导入”就可以得到你想要的结果:我们的修改以及新纪录都应该被载入到了Odoo中。

In the example seen above, the user responsible for each task is a related record in the users model, with a many to one (or foreign key) relation. The column name used for it was user_id/id and the eld values were External IDs for the related records, such as base.user_root for the administrator user.

在上面的例子中,用户负责的每个一个任务都是用户模型的关联记录,

Relation columns should have /id appended to their name, if using External IDs, or /.id, if using database (numeric) IDs. Alternatively, a colon (:) can be used in place of the slash for the same effect.

如果使用外部ID的话,关联列应该将/id追加到自己的名字上,如果使用数据库(数字形式的)ID则使用/.id

Similarly, many to many relations are also supported. An example of a many to many relations is the one between Users and Groups: each User can be in many Groups, and each Group can have many Users. The column name for this type offi eld should have appended a /id. The field values accept a comma-separated list of External IDs, surrounded by double quotes.

类似的,“多对多”关系也是被支持的。一个多对多关系的例子就是用户和组之间的关系:每个用户都可能属于多个组,而每个组也可以拥有多个用户。

For example, the to-do task follower is a many-to-many relation between To-do Tasks and Partners. It’s column name could be follower_ids/id and a field value with two followers could be:

例如,在 To-do Tasks和Partners之间to-do task的关注者是一个多对多关系。它的列名称是follower_ids/id,而且一个字段值拥有两个关注者:

  1. "__export__.res_partner_1,__export__.res_partner_2"

Finally, one to many relations can also be imported through a CSV. The typical example of this type of relations is a document “head” with several “lines”.

最后,“一对多”关系也可以通过CSV来导入。这种关系类型的典型例子是一个文档“头部”含有多个“行”。

We can see an example for such a relation in the company model (form view available in the Settings menu): a company can have several bank accounts, each with its own details, and each bank account belongs to (has a many-to-one relation with) only one company.

我们看到company模型中就有这类关系的一个例子(“设置”菜单中可用的表单视图):一家公司拥有多个银行帐户,每个账户都拥有自己的具体内容,而且每个银行帐户都只属于(属于多对一的关系)一家公司。

It’s possible to import companies along with their bank accounts in a single file. For this, some columns will correspond to the company, and other columns will correspond to the bank account details. The bank details column names should be pre xed with the one-to-many elds linking the company to the banks; bank_ids in this case.

在单个文件中可以使用银行帐户导入公司。为此,

The first bank account details goes in the same row as its related company data. The next bank account’s details go in the next rows, but only the bank details related columns should have values; the company data columns should be empty in those lines.

第一个银行帐户的细节放到了相同的行。

Here is an example loading a company with three banks:

下面是一个使用三个银行载入一个公司的例子:

  1. id,name,bank_ids/id,bank_ids/acc_number,bank_ids/state
  2. base.main_company,YourCompany,__export__.res_partner_
  3. bank_4,123456789,bank
  4. ,,__export__.res_partner_bank_5,135792468,bank
  5. ,,__export__.res_partner_bank_6,1122334455,bank

Notice that the two last lines begin with two commas: this corresponds to empty values in the first two columns, id and name, regarding the head company data. But the remaining columns, regarding bank accounts, have the values for the second and third bank records.

注意,最后两行以两个逗号开始:这对应了头两行中的空值,id和name——公司数据的头部。但是剩下的列,像银行帐户,拥有

These are the essentials on working with export and import from the GUI. It’s useful to set up data in new Odoo instances, or to prepare data files to be included in Odoo modules. Next we will learn more about using data les in modules.

从GUI导出和导入这些工作都是相当基础的。在新的Odoo实例中设置数据相当实用,或者准备需要包含在Odoo模块中的数据文件。接下来,我们会学习更多在模块中使用数据文件的内容。

Module data 模块数据

Modules use data files to load their configurations into the database, initial data and demonstration data. This can be done using both CSV and XML files. For completeness, the YAML file format can also be used, but this is rarely used for data loading, so we won’t be discussing it.

模块使用数据文件将配置载入到数据库,初始化数据和说明数据。使用CSV文件和XML文件可以实现这个目的。为了实现的完整性,YAML文件格式也可以使用,在这种格式很少用来到数据载入上,所以,我们不会讨论他。

CSV files used by modules are exactly the same as those we have seen and used for the import feature. When using them in modules, the only additional restriction is that the file name must match the name of the model to which the data will be loaded.

模块使用的CSV文件和我们之前看过的用来导入功能的CSV完全一样。当在模块中应用这些文件时,唯一一个额外限制就是文件名称必须匹配会载入数据的模型的名称。

A common example is security access, to load into the ir.model.acess model. This is usually done using CSV files, and they should be named ir.model.acess.csv.

常见的一个例子是安全访问,载入到ir.model.acess模型。我们通常使用CSV文件来完成这项操作,而且CSV文件应该使用名称ir.model.acess.csv

Demonstration data 演示数据

Odoo modules may install demo data. This is useful to provide usage examples for a module and data sets to be used in tests. It’s considered good practice for modules to provide demonstration data. Demonstration data for a module is declared using the demo attribute of the __openerp__.py manifest file. Just like the data attribute, it is a list of file names with the corresponding relative paths inside the module.

Odoo模块也可以安装演示数据。在测试的时候这个办法为模块和数据集提供了很有用的例子。模块的最佳实践被认为是提供演示数据。模块的演示数据使用清单文件__openerp__.py的demo属性来声明。和data属性一样,这是一个拥有模块内部中相对路径的文件名称列表。

We will be adding demonstration data to our todo_user module. We can start by exporting some data from the to-do tasks, as explained in the previous section. Next we should save that data in the todo_user directory with file name todo.task.csv. Since this data will be owned by our module, we should edit the id values to replace the __export__ prefix in the identifiers with the module technical name.

我们对todo_user模块添加示范数据。如前一节所说,我们从to-do tasks导入一些数据开始。接下来我们应该在todo_user使用文件名todo.task.csv来保存这份数据。因为这份数据时自定义模块所有,所以在标识符中,我们应该编辑id的值,使用模块技术名来替换__export__前缀。

As an example our todo.task.csv data file might look like this:

我们的例子中的todo.task.csv数据文件看起来是这个样子的:

  1. id,name,user_id/id,date_deadline
  2. todo_task_a,"Install Odoo","base.user_root","2015-01-30"
  3. todo_task_b","Create dev database","base.user_root",""

We must not forget to add this data file to the __openerp__.py manifest demo attribute:

我们一定不能忘记将这个数据文件添加到清单文件__openerp__.py的demo属性中:

  1. 'demo': ['todo.task.csv'],

Next time we update the module, as long as it was installed with demo data enabled, the content of the file will be imported. Note that this data will be rewritten whenever a module upgrade is performed.

下一次,我们更新模块时,只要模块安装了demo数据,文件的内容就可以被导入了。注意,不论何时,该数据在模块执行升级时便会被重写。

XML files can also be used for demonstration data. Their file names are not required to match the model to load, because the XML format is much richer and that information is provided by the XML elements inside the file.

XML文件也可以被用做示范数据。它们的文件名并不需要匹配被载入的模型,因为XML格式更为丰富,需要的信息由

Let’s learn more about what XML data files allow us to do that CSV files don’t.

让我们来学习更多的关系XML数据文件可以做到而CSV文件不能做的事情。

XML data files XML数据文件

While CSV files provide a simple and compact format to serialize data, XML files are more powerful and give more control over the loading process.

XML文件更为强大、可以更为牢固地控制载入过程, 而CSV文件对序列化数据提供了一个简单而小巧的格式。

We have already used XML data files in the previous chapters. The user interface components, such as views and menu items, are in fact records stored in system models. The XML files in the modules are a means used to load those records into the server.

在之前的章节我们已经使用XML数据。用户接口组件,比如视图和菜单选项中的实际记录是存储在系统模型中的。模块中的XML文件被用来载入这些记录到服务器。

To showcase this, we will add a second data file to the todo_user module, named todo_data.xml, with the following content:

为了说明这种情况,我们添加第二个称作todo_data.xml的包含下列内容的数据文件到todo_user模块:

  1. <?xml version="1.0"?>
  2. <openerp>
  3. <data>
  4. <!-- Data to load -->
  5. <record model="todo.task" id="todo_task_c">
  6. <field name="name">Reinstall Odoo</field>
  7. <field name="user_id" ref="base.user_root" />
  8. <field name="date_deadline">2015-01-30</field>
  9. </record>
  10. </data>
  11. </openerp>

This XML is equivalent to the CSV data file we have just seen in the previous section.

这个XML等同于我们在前一节见到的CSV数据文件。

XML data files have a <openerp> element containing <data> elements, inside of which we can have have several <record> elements, corresponding to the CSV data rows.

XML数据文件拥有一个包含<data>元素的<openerp>元素,这其中我们可以拥有多个对应到CSV数据列的<record>元素。

A <record> element has two mandatory attributes, model and id (the external identifier for the record), and contains a <field> tag for each field to write on.

<record>元素拥有两个必写属性,modelid(记录的外部标识符),并为每个需要编写的字段的附加了<field>标签。

Note that the slash notation in field names is not available here: we can’t use <field name="user_id/id">. Instead the ref special attribute is used to reference External IDs. We’ll discuss the values for the relational “to many” fields in a moment.

注意字段名称中的反斜杠记号在这里是不可用的:我们不能使用<field name="user_id/id">。相反,ref 特殊属性被用来引用外部ID。一会儿我们将讨论到关联“对多”字段的值。

The data noupdate attribute 数据的非更新属性

When the data loading is repeated, existing records from the previous run are rewritten.

当数据载入发生重复时,之前运行的已存在记录会被重写。

This is important to keep in mind: it means that upgrading a module will overwrite any manual changes that might have been made to the data. Notably, if views were modified with customizations, those changes will be lost with the next module upgrade. The correct procedure is to instead create inherited views for the changes we need, as discussed in the Chapter 3, Inheritance – Extending Existing Applications.

牢记这条规则在心是非常重要的:这就是说升级一个模块将会重写任何应用到数据的手动变更。特别的,如果视图应用了自定义修改,那么这些变更在下一次模块升级时被丢弃。正确的流程是为我们需要应用的变更创建继承视图,一如在第三章,继承——扩展现有模型所讨论的那样。

This overwrite behavior is the default, but it can be changed, so that when an already created record is loaded again no change is made to it. This is done by adding to the <data> element a noupdate="1" attribute. With this, its records will be created the first time they are loaded, and in subsequent module upgrades nothing will be done to them.
重写行为是默认的,但是也可以改变的,所以一个已经创建过的记录被再次载入时变更被应用到记录。通过对<data>元素添加一个noupdate="1"属性就可以实现。这样,记录在模型第一次载入时被创建,而且之后的模块升级也不会影响到这些数据。

This allows for manually made customizations to be safe from module upgrades. It is often used with record access rules, allowing them to be adapted to implementation specific needs.

这样做就允许手动。这经常和记录访问规则一起使用,

It is also possible to have more than one <data> section in the same XML file. We can take advantage of this to have a data set with noupdate=”1” and another with noupdate=”0”.

在相同的XML文件中可以拥有不止一个<data>区域。我们

The noupdate flag is stored in the External Identifier information for each record. It’s possible to edit it directly using the External Identifier form available in the Technical menu, with the Non Updatable checkbox.

每个记录的odoWizard旗标都存储在了外部标识符中。在技术菜单中,可以直接使用外部标识符表单来对Non Updatable复选框进行编辑。

Tips

The noupdate attribute is tricky when developing modules, because changes made to the data later will be ignored, and Odoo won’t pick up later modifications. A solution is to keep noupdate="0" during development and only set it to 1 once finished.

提示

在开发时应用noupdate属性是个技巧,因为对数据的变更在之后会被忽略掉,而且Odoo也不会接受之后的修改。解决方案时在开发时保证noupdate="0"而且尽在开发完成后才设置为1.

Defining Records in XML 在XML中定义记录

Each <record> element has two basic attributes, id and model, and contains <field> elements assigning values to each column. As mentioned before, the id attribute corresponds to the record’s External ID and the model to the target model where the record will be written. The elements have available a few different ways to assign values. Let’s look at them in detail.

<record>元素都拥有两个基本属性,id和model,并包含赋值到每个列的<field>元素。就像之前所说的那样,id属性对应到记录的外部ID,model对应到需要写入记录的模型中。元素有好几种不同的方法来赋值。让我们来仔细看看。

Setting field values 设置字段的值

The <record> element defines a data record, and contains elements to set values on each field.
The name attribute of the eld element identi es the eld to be written.
The value to write is the element content: the text between the eld’s opening and closing tag. In general this is also suitable to set non-text values: for Booleans, “0”/ “1” or “False”/“True” values will be correctly converted; for dates and datetimes, stringswith”YYYY-MM-DD”and”YYYY-MM-DD HH:MI:SS”willbeconvertedproperly.

<record>元素定义了数据记录,包含

Setting values using expressions 使用表达式设置值

A more advanced alternative to define a field value is using the eval attribute instead. This evaluates a Python expression and assigns the resulting value to the field.

更为高级的可以选择的是使用evle属性定义一个字段的值。该方法通过对Python表达式求值,然后对字段赋予结果值。

The expression is evaluated in a context that, besides Python built-ins, also has some additional identifiers available. Let’s have a look at them.

在上下文中表达式的求值除了可以使用Python内建的方法之外,还可以使用一些额外的标识符。我们就来看看这些它们。

To handle dates, the following modules are available: time, datetime, timedelta and relativedelta. They allow calculating date values, something that is frequently used in demonstration (and test) data. For example, to set a value to yesterday we would use:

为了处理日期,下列模块是使用的:time, datetime, timedelta 以及 relativedelta。它们能够计算日期的值,

  1. <field name="expiration_date" eval="(datetime.now() + timedelta(-1)).strftime('%Y-%m-%d')" />

Also available in the evaluation context is the ref() function, used to translate an External ID into the corresponding database ID. This can be used to set values for relational fields. As an example, we have used it before to set the value for the user_id:

在求值上下文中还可以使用的是ref()函数,该函数用来翻译外部ID到对象的数据库ID。它可以用来设置关联字段的值。例如,我们之前曾使用它为user_id设置值。

  1. <field name="user_id" eval="ref('base.group_user')" />

The evaluation context also has a reference available to the current Model being written through obj. It can be used together with ref() to access values from other records. Here is an example from the Sales module:

计算上下文也可以

  1. <value model="sale.order" eval="obj(ref('test_order_1')).amount_total" />

Setting values for relation fields 为关联字段设置值

We have just seen how to set a value on a many-to-one relation field, such as user_id, using the eval attribute with a ref() function. But there is a simpler way.

我们刚刚看到了如何在一个多对一关联字段设置值,比如user_id,就可以使用含有ref()函数的eval属性。不过这里有一个简单的办法。

The element also has a ref attribute to set the value for a many-to-one field using an External ID. Using it, we can set the value for user_id using just:

元素也包含ref属性来使用外部ID为多对一字段设置值。使用这个属性我们可以设置

  1. <field name="user_id" ref="base.group_user" />

For one-to-many and many-to-many fields, a list of related IDs is expected, so a different syntax is needed, and Odoo provides a special syntax to write on this type of fields.

对于一对多和多对多字典,需要用到关联ID的列表,所以也就需要不同的语法来实现,而且Odoo也为提供了特殊的语法来写这种类型的字段。

The following example, taken from the Fleet app, replaces the list of related records of a tag_ids field:

下面的例子,取自Fleet应用,它:

  1. <field name="tag_ids"
  2. eval="[(6,0,
  3. [ref('vehicle_tag_leasing'),
  4. ref('fleet.vehicle_tag_compact'),
  5. ref('fleet.vehicle_tag_senior')])]" />

To write on a to many-field we use a list of triples. Each triple is a write command that does different things according to the code used:

我们使用一个三元组列表来重写多个字段。对于所用的代码,每个三元组都是一个实现不同事情的写命令:

  • (0,_ ,{‘field’: value}): This creates a new record and links it to this one
  • (1,id,{‘field’: value}): This updates values on an already linked record
  • (2,id,_): This unlinks and deletes a related record
  • (3,id,_): This unlinks but does not delete a related record
  • (4,id,_): This links an already existing record
  • (5,,): This unlinks but does not delete all linked records
  • (6,_,[ids]): This replaces the list of linked records with the provided list

  • (0,_ ,{‘field’: value}): 创建一的新的记录,并把新纪录链接过来。

  • (1,id,{‘field’: value}): 对一个已有的链接记录更新值。
  • (2,id,_): unlink 和 delete 一条关联记录。
  • (3,id,_): 对关联的记录仅执行unlink而不是delete
  • (4,id,_): 链接到一条现有的记录。
  • (5,,):对全部链接的记录执行unlink而不是delete。
  • (6,_,[ids]):使用用户提供的链接来替换链接记录的列表。

The underscore symbol used above represents irrelevant values, usually filled with 0 or False.

上面用到的下划线符号表示无关联的值,通常使用0或者False来填充。

Shortcuts for frequently used Models 常用模型的快捷键

If we go back to Chapter 2, Building Your First Odoo Application, we can find in the XML files elements other than <record>, such as <act_window> and <menuitem>.

如果我们回到第二章,

These are convenient shortcuts for frequently used Models that can also be loaded using regular <record> elements. They load data into base Models supporting the user interface and will be explored in more detail later, in Chapter 6, Views - Designing the User Interface.

这些方便的捷径常常使用的是可以使用普通<record>元素

For reference, so that we can better understand XML files we may encounter in existing modules, the following shortcut elements are available with the corresponding Models they load data into:

所以,我们可以更好的理解可能在现有模块中遇到的XML文件,下面的快捷元素

  • <act_window>: This is the Window Actions model ir.actions.act_window
  • <menuitem>: This is the Menu Items model ir.ui.menu
  • <report>: This is the Report Actions model ir.actions.report.xml
  • <template>: This is View QWeb Templates stored in model ir.ui.view
  • <url>: This is the URL Actions model ir.actions.act_url

  • <act_window>:ir.actions.act_window模型的窗口应用

  • <menuitem>:ir.ui.menu模型的菜单选项
  • <report>:

Other actions in XML data files XML数据文件中的其它动作

Until now we have seen how to add or update data using XML files. But XML files also allow performing other types of actions, sometimes needed to set up data. In particular, they are capable in deleting the data, execute arbitrary model methods, and trigger work ow events.

到现在为止,我们已经见到了如何使用XML文件添加或者更新数据。不过,XML文件也能够执行其他类型的动作,。特别是,它们它们兼容于

Deleting records 删除记录

To delete a data record we use the element, providing it with either an id or a search domain to nd the target record.

要删除一条数据记录我们可以使用元素,

In Chapter 3, Inheritance – Extending Existing Applications, we had the need to remove a record rule added by the to-do app. In the todo_user/security/todo_access_ rules.xml file a element was used, with a search domain to find the record to delete:

在第三章,继承——扩展现有应用中,我们需要移除由to-do应用所添加的记录规则。在todo_user/security/todo_access_ rules.xml文件中使用的是含有一个查找需要删除记录的搜索域的元素:

  1. <delete
  2. model="ir.rule"
  3. search="[('id','=',ref('todo_app.todo_task_user_rule'))]"
  4. />

In this case the same exact effect could be achieved using the id attribute to identify the record to delete:

在这个例子中,使用id属性标识需要删除的记录可以使用同样的结果:

  1. <delete model="ir.rule" id="todo_app.todo_task_user_rule" />

Triggering functions and work flows 触发函数以及工作流

An XML file can also execute methods during its load process through the element. This can be used to set up demo and test data. For example, in the membership module it is used to create demonstration membership invoices:

XML文件在通过 元素载入时也可以执行方法。这个方法可以用来设置示例和测试数据。例如, 在membership模块中,这个方法用来创建membership发票的示例:

  1. <function
  2. model="res.partner"
  3. name="create_membership_invoice"
  4. eval="(ref('base.res_partner_2'),
  5. ref('membership_0'),
  6. {'amount':180})"
  7. />

This is calling the create_membership_invoice() method of the res.partner model. The arguments are passed as a tuple in the eval attribute. In this case we have a tuple with three arguments: the Partner ID, the Membership ID and a dictionary containing the invoice amount.

上面的代码调用的是res.partner模型的create_membership_invoice()方法。

Another way XML data files can perform actions is by triggering Odoo work flows, through the element.

另外XML数据文件能够透过<workflow>元素执行由Odoo工作流出发的动作。

Work flows can, for example, change the state of a sales order or convert it into an invoice. Here is an example taken from the sale module, converting a draft sales order to the confirmed state:

例如,工作流能够过改变销售订单的状态,或者把它转换为一张发票。下面是一个取自销售模块的例子,它请求临时销售订单转换为已确认状态:

  1. <workflow model="sale.order"
  2. ref="sale_order_4" action="order_confirm" />

The model is self-explanatory by now, and ref identifies the work flow instance we are acting upon. The action is the work flow signal sent to that work ow instance.

现在,模块的意义是不解自明的,ref标识出我们需要执行动作的工作流实例。

Summary 总结

We have learned all the essentials about data serialization, and gained a better understanding of the XML aspects we saw in the previous chapters.

我们已经学写了数据序列化的基础,

We also spent some time understanding External Identifiers, a central concept for data handling in general, and for module configurations in particular.

我们也花了一些时间来理解外部标识符,通常情况下的数据处理的核心概念,以及特殊应用场景中模块的配置。

XML data files were explained in detail. We learned about the several options available to set values on fields and also to perform actions such as deleting records and calling model methods.

XML数据文件详细进行了说明。我们学习

CSV files and the data import/export features were also explained. These are valuable tools for Odoo initial setup or for mass editing of data.

CSV文件和数据导入/导出功能也进行了说明。这些非常有用的工具被用在了Odoo初始化设置以及数据的批量修改上。

In the next chapter are will explore in detail how to build Odoo models and later learn more about building their user interfaces.

在接下来的章节,我们会浏览构建Odoo模型的细节,之后学习更多关于模型用户接口的构建。