定义模块数据¶
重要
本教程是 服务器框架101 教程的扩展。确保您已完成它并使用您构建的 estate 模块作为本教程中练习的基础。
数据类型¶
主数据¶
主数据通常是模块的技术或业务需求的一部分。换句话说,这些数据通常是模块正常工作所必需的。安装模块时将始终安装此数据。
自从我们定义了 views 和 actions 以来,我们之前已经见过技术数据。这些是主数据的一种。
除了技术数据之外,还可以定义业务数据,例如国家、货币、计量单位以及完整的国家本地化(法律报告、税务定义、会计科目表)等等…
演示数据¶
除了模块正常工作所需的主数据外,我们还可以提供用于演示目的的数据:
帮助销售代表快速制作演示。
为开发人员提供一组工作数据来测试新功能,并查看这些新功能与他们可能没有自己添加的数据的外观如何。
测试数据是否正确加载,不会引发错误。
设置创建新数据库时要快速使用的大部分功能。
数据库管理器允许您使用演示数据创建数据库。可以通过命令行使用 --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
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
您添加的优惠应始终处于与模块安装相关的日期。
search¶
有时,您需要调用 ORM 来执行“search”。这对于 CSV 格式来说是不可行的。
<odoo>
<record id="id1" model="account.move.line">
<field name="account_id" search="[
('user_type_id', '=', ref('account.data_account_type_direct_costs')),
('company_id', '=', obj().env.company.id)]
"/>
</record>
</odoo>
在此代码片段中,它是必需的,因为主数据取决于安装的本地化。
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 约束的所有功能。
它可以帮助大大加快导入时间`with huge files <https://github.com/odoo/enterprise/blob/d46cceef8c594b9056d0115edb7169e207a5986f/product_unspsc/hooks.py#L19>`__。
对于更复杂的导入,例如 translations。
可能有必要 initialize the database。