定义模块数据¶
重要
This tutorial is an extension of the Server framework 101 tutorial. Make sure you have
completed it and use the estate
module you have built as a base for the exercises in this
tutorial.
数据类型¶
主数据¶
主数据通常是模块的技术或业务需求的一部分。换句话说,这些数据通常是模块正常运行所必需的。这些数据将始终在安装模块时安装。
We already met technical data previously since we have defined views and actions. Those are one kind of master data.
除了技术数据外,还可以定义业务数据,例如国家、货币、计量单位,以及完整的国家本地化(法律报告、税务定义、账户图表)等等……
演示数据¶
除了主数据(模块正常工作所需的数据)外,我们还希望拥有演示目的的数据:
帮助销售代表快速制作演示文稿。
为开发人员准备一组工作数据,以便测试新功能并查看这些新功能与他们可能没有添加的数据的外观。
测试数据是否正确加载,且不会引发错误。
快速设置大部分要在创建新数据库时使用的功能。
如果您没有明确表示不需要,启动服务器时将自动加载演示数据。这可以在数据库管理器或命令行中完成。
$ ./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:
[...]
--without-demo=WITHOUT_DEMO
disable loading demo data for modules to be installed
(comma-separated, use "all" for all modules). Requires
-d and -i. Default is none
[...]
$ ./odoo-bin --addons-path=... -d db -i account --without-demo=all
数据声明¶
清单¶
参考: 有关此主题的文档可以在 模块清单 中找到。
数据可以以 CSV 或 XML 的形式声明。每个包含数据的文件都必须在清单中添加才能加载。
在清单中添加新数据的键是 data
(主数据)和 demo
(演示数据)。两个值都应该是一个字符串列表,表示声明数据的相对路径。
通常,演示数据位于 demo
文件夹中,视图和操作位于 views
文件夹中,与安全相关的数据位于 security
文件夹中,其他数据位于 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 数据文件 中找到。
声明简单数据的最简单方法是使用CSV格式。但是,这种格式在功能方面有限:对于长列表中的简单模型,请使用它,但否则请使用XML。
id,field_a,field_b,related_id:id
id1,valueA1,valueB1,module.relatedid
id2,valueA2,valueB2,module.relatedid
Exercise
为 estate
模块添加一些标准的房地产物业类型:住宅、商业、工业和土地。这些应该始终被安装。
XML¶
参考: 有关此主题的文档可以在 数据文件 中找到。
当要创建的数据更加复杂时,使用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年01月01日 |
期望价格 |
160万 |
10万 |
销售价格 |
120,000 |
|
卧室数 |
6 |
1 |
生活区域 |
100 |
10 |
门面 |
4 |
4 |
车库 |
真 |
假 |
花园 |
真 |
|
花园面积 |
十万 |
|
花园方向 |
南 |
数据扩展¶
During the Core Training, we saw in the Chapter 12: Inheritance chapter we could inherit (extend) an existing view. This was a special case of data extension: any data can be extended in a module.
当您在新模块中向现有模型添加新字段时,您可能希望在依赖模块中创建的记录上填充这些字段。这可以通过给出要扩展的记录的 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
键进行设置。该键的值是要链接的记录的 xml_id
。请记住, xml_id
由首次声明数据的模块的名称组成,后跟一个点,后跟记录的 id
(如果您在声明模块中,则只使用 id
也可以)。
<odoo>
<record id="id1" model="tutorial.example">
<field name="related_id" ref="module.relatedid"/>
</record>
</odoo>
Exercise
为您创建的属性创建一些演示数据报价。
使用 base
中定义的合作伙伴创建报价
合作伙伴 |
房地产 |
价格 |
有效期 |
---|---|---|---|
蓝色内饰 |
大别墅 |
10000 |
14 |
蓝色内饰 |
大别墅 |
一百五十万 |
14 |
装饰迷 |
大别墅 |
1500001 |
14 |
Exercise
请确保您的两个演示属性的属性类型均设置为住宅。
eval
¶
The value to assign to a field is not always a simple string and you might need to compute it. It can also be used to optimize the insertion of related values, or because a constraint forces you to add the related values in batch. See :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
创建一个新的Property,但这次在与Offers相关联的One2many字段中直接创建一些报价。
访问数据¶
警告
永远不要在演示数据声明之外访问演示数据,即使在测试中也不行。
有多种方式可以访问主/演示数据。
在Python代码中,您可以使用 env.ref(self, xml_id, raise_if_not_found=True)
方法。它返回与您指定的 xml_id
相关联的记录集。
在 XML 中,您可以像这样使用 ref
键
<odoo>
<record id="id1" model="tutorial.example">
<field name="related_id" ref="module.relatedid"/>
</record>
</odoo>
它将调用ref方法,并将返回的记录的id存储在类型为 tutorial.example
且id为 id1
的记录的 related_id
字段中。
在 CSV 中,列的标题必须以 :id
或 /id
结尾。
id,parent_id:id,name
"child1","module.parent","Name1"
"child2","module.parent","Name2"
"child3","module.parent","Name3"
In SQL, it is more complicated, see the advanced section.
警告
用户始终可以删除数据。在编码时要始终考虑到这一点,采取防御性编程。
高级¶
什么是XML id?¶
由于我们不想在数据库的每个SQL表中都有一个列 xml_id
,因此我们需要一种机制来存储它。这是通过 ir.model.data
模型完成的。
它包含了记录的名称( xml_id
),以及定义它的模块,定义它的模型和它的id。
没有更新¶
使用 noupdate
标志创建的记录在升级创建它们的模块时不会被更新,但如果它们不存在,则会被创建。
注解
odoo-bin -i module
will bypass this setting and always load the data. But normally
one shouldn’t do this on a production database.
<odoo noupdate="1">
<record id="id1" model="model">
<field name="fieldA" eval="True"/>
</record>
</odoo>
导入为SQL¶
在某些情况下,直接在SQL中进行导入是有意义的。但是,这是不鼓励的,因为它绕过了ORM的所有功能,包括计算字段(包括元数据)和Python约束。
它可以帮助大大加快导入时间 with huge files.
对于更复杂的导入,例如 translations。
有时候需要 初始化数据库。