定义模块数据

重要

本教程是 服务器框架101 教程的扩展。确保您已完成它并使用您构建的 estate 模块作为本教程中练习的基础。

数据类型

主数据

主数据通常是模块的技术或业务需求的一部分。换句话说,这些数据通常是模块正常工作所必需的。安装模块时将始终安装此数据。

自从我们定义了 viewsactions 以来,我们之前已经见过技术数据。这些是主数据的一种。

除了技术数据之外,还可以定义业务数据,例如国家、货币、计量单位以及完整的国家本地化(法律报告、税务定义、会计科目表)等等…

演示数据

除了模块正常工作所需的主数据外,我们还可以提供用于演示目的的数据:

  • 帮助销售代表快速制作演示。

  • 为开发人员提供一组工作数据来测试新功能,并查看这些新功能与他们可能没有自己添加的数据的外观如何。

  • 测试数据是否正确加载,不会引发错误。

  • 设置创建新数据库时要快速使用的大部分功能。

数据库管理器允许您使用演示数据创建数据库。可以通过命令行使用 --with-demo 来实现相同的效果。

$ ./odoo-bin -h
Usage: odoo-bin [options]

Options:
--version             show program's version number and exit
-h, --help            show this help message and exit

Common options:
  [...]
  --with-demo         install demo data in new databases
[...]

$ ./odoo-bin --addons-path=... -d new-db -i base --with-demo

数据声明

显现

参考:与此主题相关的文档可以在 Module Manifests 中找到。

数据以 CSV 或 XML 格式声明。每个包含数据的文件都必须添加到清单中才能加载。

在清单中用于添加新数据的键是演示数据的“data` for the master data and ``demo`”。这两个值都应该是表示声明数据的文件的相对路径的字符串列表。

通常,演示数据位于 demo folder, views and actions are in a views folder, security related data is in a security folder, and other data is in a data 文件夹中。

如果您的工作树如下所示:

estate
├── data
│   └── master_data.xml
├── demo
│   └── demo_data.xml
├── models
│   ├── *.py
│   └── __init__.py
├── security
│   └── ir.model.access.csv
├── views
│   └── estate_property_offer_views.xml
├── __init__.py
└── __manifest__.py

您的清单应如下所示:

# -*- coding: utf-8 -*-

{
    "name": "Real Estate",
    "depends": [
        ...
    ],
    "data": [
        "security/ir.model.access.csv",  # CSV and XML files are loaded at the same place
        "views/estate_property_offer_views.xml",  # Views are data too
        "data/master_data.xml",  # Split the data in multiple files depending on the model
    ],
    "demo": [
        "demo/demo_data.xml",
    ]
    "application": True,
}

CSV

参考:与此主题相关的文档可以在 CSV data files 中找到。

声明简单数据的最简单方法是使用 CSV 格式。然而,这在功能方面受到限制:将其用于简单模型的长列表,但在其他情况下更喜欢 XML。

id,field_a,field_b,related_id:id
id1,valueA1,valueB1,module.relatedid
id2,valueA2,valueB2,module.relatedid

小技巧

您的 IDE 可能有一个扩展来突出显示 CSV 文件的语法

Exercise

estate 模块添加一些标准房地产类型:住宅、商业、工业和土地。应始终安装这些。

XML

参考:与此主题相关的文档可以在 Data Files 中找到。

当要创建的数据比较复杂时,使用 XML 来创建可能会很有用,甚至是必要的。

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="field_a">valueA1</field>
    <field name="field_b">valueB1</field>
  </record>

  <record id="id2" model="tutorial.example">
    <field name="field_a">valueA2</field>
    <field name="field_b">valueB2</field>
  </record>
</odoo>

Exercise

estate 模块创建一些演示数据。

场地

价值观

价值观

姓名

大别墅

拖车回家

状态

新的

取消

描述

一栋又漂亮又大的别墅

家在拖车公园

邮政编码

12345

54321

日期_可用性

2020-02-02

1970年1月1日

预期价格

1,600,000

100,000

销售价格

120,000

卧室

6

1

生活区

100

10

外墙

4

4

车库

真的

错误的

花园

真的

花园区

100000

花园方向

数据扩展

在核心训练期间,我们在 第12章:继承 章节中看到我们可以继承(扩展)现有视图。这是数据扩展的一个特例:任何数据都可以在模块中扩展。

当您向新模块中的现有模型添加新字段时,您可能希望将这些字段填充到您所依赖的模块中创建的记录中。这是通过提供您想要扩展的记录的 xml_id 来完成的。它不会替换它,在这种情况下,我们会将两条记录的“field_c”设置为给定值。

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="field_c">valueC1</field>
  </record>

  <record id="id2" model="tutorial.example">
    <field name="field_c">valueC2</field>
  </record>
</odoo>

ref

可以使用“ref` key. The value of that key is the xml_id of the record you want to link. Remember the xml_id is composed of the name of the module where the data is first declared, followed by a dot, followed by the id of the record (just the ``id`”设置相关字段,如果您在声明它的模块中也可以。

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="related_id" ref="module.relatedid"/>
  </record>
</odoo>

Exercise

为您创建的属性创建一些演示数据。

使用“base”中定义的合作伙伴创建报价

伙伴

财产

价格

有效性

蔚蓝内饰

大别墅

10000

14

蔚蓝内饰

大别墅

1500000

14

装饰瘾君子

大别墅

1500001

14

Exercise

确保您创建的两个演示房产的房产类型均设置为住宅。

eval

分配给字段的值并不总是简单的字符串,您可能需要计算它。它还可用于优化相关值的插入,或者因为约束强制您批量添加相关值。请参阅:Add X2many fields

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="year" eval="datetime.now().year+1"/>
  </record>
</odoo>

Exercise

您添加的优惠应始终处于与模块安装相关的日期。

function

加载数据时您可能还需要执行 python 代码。

<function model="tutorial.example" name="action_validate">
    <value eval="[ref('demo_invoice_1')]"/>
</function>

Exercise

使用“接受报价”按钮验证演示数据报价之一。拒绝其他人。

添加 X2many 字段

参考:与此主题相关的文档可以在 Command 中找到。

如果需要在 One2many 或 Many2many 字段中添加相关数据,可以使用 Command 方法来完成。

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="related_ids" eval="[
        Command.create({
            'name': 'My name',
        }),
        Command.create({
            'name': 'Your name',
        }),
        Command.link(ref('model.xml_id')),
    ]"/>
  </record>
</odoo>

Exercise

创建一个新属性,但这次直接在链接到报价的 One2many 字段内创建一些报价。

访问数据

警告

您永远不应该在演示数据声明之外访问演示数据,即使在测试中也是如此。

有多种方法可以访问主/演示数据。

在Python代码中,您可以使用您指定的``env.ref(self, xml_id, raise_if_not_found=True)`` method. It returns the recordset linked to the xml_id

在 XML 中,您可以像这样使用 ref

<odoo>
  <record id="id1" model="tutorial.example">
    <field name="related_id" ref="module.relatedid"/>
  </record>
</odoo>

它将调用 ref 方法,并将返回的记录的 id 存储在字段 related_id of the record of type tutorial.example with id id1 中。

在 CSV 中,列标题必须以“:id` or ``/id`”作为后缀。

id,parent_id:id,name
"child1","module.parent","Name1"
"child2","module.parent","Name2"
"child3","module.parent","Name3"

在 SQL 中,更复杂,请参见 the advanced section

警告

用户始终可以删除数据。考虑到这一点,始终进行防御性编码。

先进的

XML ID 是什么?

因为我们不需要列``xml_id`` in every single SQL table of the database, we need a mechanism to store it. This is done with the ``ir.model.data``模型。

它包含记录的名称(xml_id)以及定义它的模块、定义它的模型以及它的 id。

无更新

使用 noupdate 标志创建的记录在升级创建它们的模块时不会更新,但如果尚不存在,则会创建它。

注解

odoo-bin -i module 将绕过此设置并始终加载数据。但通常不应在生产数据库上执行此操作。

<odoo noupdate="1">
  <record id="id1" model="model">
    <field name="fieldA" eval="True"/>
  </record>
</odoo>

导入为 SQL

在某些情况下,直接在 SQL 中进行导入是有意义的。然而,这是不鼓励的,因为它绕过了 ORM、计算字段(包括元数据)和 python 约束的所有功能。

注解

通常使用原始 SQL 也会绕过 ACL 并增加注入的风险。

参考Security in Odoo