第 7 章:模型之间的关系¶
在( 上一章 )涵盖了为包含基本字段的模型创建自定义视图的内容。然而,在任何实际业务场景中,我们不仅需要一个模型,还需要模型之间的关联。可以很容易想象,一个模型包含客户信息,另一个模型包含用户列表。在任何现有的业务模型中,您可能都需要引用客户或用户。
在我们的房地产模块中,我们希望为房产添加以下信息:
购买房产的客户
出售房产的房地产代理
房产类型:房屋、公寓、顶层公寓、城堡……
描述房产的一组标签:舒适、翻新……
收到的报价列表
多对一(Many2one)¶
参考:与此主题相关的文档可在 Many2one
中找到。
注解
目标:在本节结束时:
应创建一个新的
estate.property.type
模型,并为其添加相应的菜单、操作和视图。

应在
estate.property
模型中添加三个多对一字段:房产类型、买家和卖家。

在我们的房地产模块中,我们需要定义“房产类型”的概念。例如,房产类型可以是房屋或公寓。根据类型对房产进行分类是一项标准的业务需求,尤其是为了优化过滤功能。
一个房产只能有一个类型,但同一类型可以分配给多个房产。这由“多对一”(many2one)概念支持。
多对一是指向另一个对象的简单链接。例如,为了在测试模型中定义与 res.partner
的链接,我们可以写::
partner_id = fields.Many2one("res.partner", string="Partner")
按照惯例,多对一字段带有 _id
后缀。然后可以通过以下方式轻松访问合作伙伴中的数据::
print(my_test_object.partner_id.name)
参见
实际上,多对一字段在表单视图中表现为一个下拉列表。
Exercise
添加房地产属性类型表。
创建
estate.property.type
模型并添加以下字段:
字段 |
类型 |
属性 |
---|---|---|
名称 |
字符 |
依赖 |
按照本节 目标 中显示的内容添加菜单。
在
estate.property
模型及其表单视图、列表视图和搜索视图中添加字段property_type_id
。
本练习是对前面章节的良好回顾:您需要创建一个 模型 ,设置 模型权限 ,添加 操作和菜单 ,并 创建视图 。
提示:别忘了在 __init__.py
中导入任何新的 Python 文件,在 __manifest.py__
中添加新的数据文件,或者添加访问权限 ;-)
再次重启服务器并刷新以查看结果!
在房地产模块中,我们仍缺少两项关于房产的信息:买家和销售人员。买家可以是任何个人,但另一方面,销售人员必须是房地产机构的员工(即Odoo用户)。
在Odoo中,我们通常会引用两个模型:
res.partner
:合作伙伴是一个物理或法律实体。它可以是公司、个人,甚至是联系地址。res.users
:系统用户。用户可以是“内部用户”,即他们可以访问Odoo后台;或者他们是“门户用户”,即无法访问后台,只能访问前端(例如,在电子商务中查看之前的订单)。
Exercise
添加买家和销售人员。
使用上述两个常见模型将买家和销售人员添加到 estate.property
模型中。它们应添加到表单视图的新选项卡中,如本节 目标 所示。
销售人员的默认值必须是当前用户。买家不应被复制。
提示:要获取默认值,请查看下面的注释或参考此示例 这里 。
注解
对象 self.env
提供对请求参数和其他有用内容的访问:
self.env.cr
或self._cr
是数据库 游标 对象;它用于查询数据库self.env.uid
或self._uid
是当前用户的数据库 IDself.env.user
是当前用户的记录self.env.context
或self._context
是上下文字典self.env.ref(xml_id)
返回与 XML ID 对应的记录self.env[model_name]
返回给定模型的实例
现在让我们来看看其他类型的关联。
多对多(Many2many)¶
参考:与此主题相关的文档可在 Many2many
中找到。
注解
目标:在本节结束时:
应创建一个新的
estate.property.tag
模型,并为其添加相应的菜单和操作。

应在
estate.property
模型中添加标签:

在我们的房地产模块中,我们需要定义“房产标签”的概念。例如,一个房产可以是“舒适”或“翻新”。
一个房产可以有 多个 标签,而一个标签也可以分配给 多个 房产。这由“多对多”( many2many )概念支持。
多对多是一种双向多对多关系:一侧的任何记录都可以与另一侧的任意数量的记录相关联。例如,为了在测试模型中定义与 account.tax
模型的链接,我们可以写::
tax_ids = fields.Many2many("account.tax", string="Taxes")
按照惯例,多对多字段带有 _ids
后缀。这意味着可以将多个税项添加到我们的测试模型中。它表现为一个记录列表,因此访问数据必须在循环中完成::
for tax in my_test_object.tax_ids:
print(tax.name)
记录列表被称为 记录集 (recordset),即一个有序的记录集合。它支持标准的Python集合操作,如 len()
和 iter()
,以及额外的集合操作,如 recs1 | recs2
。
一对多(One2many)¶
参考:与此主题相关的文档可在 One2many
中找到。
注解
目标:在本节结束时:
应创建一个新的
estate.property.offer
模型,并为其添加相应的表单视图和列表视图。应在
estate.property
模型中添加报价:

在我们的房地产模块中,我们需要定义“房产报价”的概念。房产报价是潜在买家向卖方提供的金额。该报价可能低于或高于预期价格。
一个报价适用于 一个 房产,但同一房产可以有 多个 报价。“多对一”( many2one )概念再次出现。然而,在这种情况下,我们希望显示特定房产的报价列表,因此我们将使用“一对多”( one2many )概念。
一对多是多对一的反向关系。例如,我们在测试模型中通过字段 partner_id
定义了与 res.partner
模型的链接。我们可以定义反向关系,即与我们的合作伙伴相关的测试模型列表::
test_ids = fields.One2many("test_model", "partner_id", string="Tests")
第一个参数称为 comodel
(关联模型),第二个参数是我们要反向关联的字段。
按照惯例,一对多字段带有 _ids
后缀。它们表现为一个记录列表,因此访问数据必须在循环中完成::
for test in partner.test_ids:
print(test.name)
Exercise
添加房地产属性报价表。
创建
estate.property.offer
模型并添加以下字段:
字段 |
类型 |
属性 |
值(Values) |
---|---|---|---|
价格 |
Float |
||
状态 |
选择 |
不复制 |
Accepted, Refused |
客户ID |
Many2one ( |
依赖 |
|
属性ID |
多对一( |
依赖 |
使用
price
、partner_id
和status
字段创建列表视图和表单视图。无需创建操作或菜单。将字段
offer_ids
添加到您的estate.property
模型及其表单视图中,如本节的 目标 所示。
这里有几点需要注意。首先,并非所有模型都需要操作或菜单。某些模型只能通过其他模型访问。在我们的练习中就是这种情况:报价始终通过房产访问。
其次,尽管 property_id
字段是必填项,我们并未将其包含在视图中。那么 Odoo 如何知道我们的报价与哪个属性相关联呢?这就是使用 Odoo 框架的魔力之一:有时事情是隐式定义的。当我们通过一对多字段创建记录时,为了方便起见,对应的多对一字段会自动填充。
还活着吗?本章绝对不是最简单的。它引入了一些新概念,同时依赖于之前介绍的所有内容。别担心, 下一章 会轻松一些 ;-)