第 7 章:模型之间的关联¶
上一章 介绍了为包含基本字段的模型创建自定义视图。然而,在任何真实的业务场景中,我们都需要不止一个模型。此外,模型之间的关联也是必不可少的。可以很容易地想象一个模型存放客户,另一个模型存放用户列表。你可能需要在任何现有业务模型中引用某个客户或用户。
在我们的房地产模块中,我们希望为房产记录以下信息:
购买该物业的客户
售出该物业的房地产经纪人
物业类型:房屋、公寓、顶层公寓、城堡……
描述物业特征的标签列表:舒适、翻新……
收到的报价列表
Many2one¶
参考:与本主题相关的文档可在 Many2one 中找到。
注解
目标:本节结束时:
应创建新的
estate.property.type模型,并包含相应的菜单、动作和视图。
应向
estate.property模型添加三个 Many2one 字段:房产类型、买家和卖家。
在我们的房地产模块中,我们想定义房产类型的概念。例如,房产类型可以是别墅或公寓。按类型对房产进行分类是标准的业务需求,尤其是为了细化筛选。
一个房产可以有 一个 类型,但同一个类型可以分配给 多个 房产。这由 many2one 概念支持。
many2one 是指向另一个对象的简单链接。例如,为了在测试模型中定义指向 res.partner 的链接,我们可以这样写:
partner_id = fields.Many2one("res.partner", string="Partner")
按照惯例,many2one 字段带有 _id 后缀。之后就可以轻松地通过以下方式访问伙伴中的数据:
print(my_test_object.partner_id.name)
更多内容
在实践中,many2one 可以看作是表单视图中的下拉列表。
练习
添加房地产房产类型数据表。
创建
estate.property.type模型并添加以下字段:
字段 |
类型 |
属性 |
|---|---|---|
name |
字符型 |
required |
按本节 目标 中所示添加菜单
将
property_type_id字段添加到estate.property模型及其表单视图、列表视图和搜索视图中
这个练习很好地回顾了前面几章的内容:你需要创建 模型,设置 模型,添加 动作和菜单,并 创建视图。
提示:不要忘记在 __init__.py 中导入所有新的 Python 文件,在 __manifest.py__ 中添加新的数据文件,或者添加访问权限 ;-)
再次重启服务器并刷新页面以查看结果!
在房地产模块中,我们还缺少两项希望在房产上看到的信息:买家和销售人员。买家可以是任何个人,但另一方面,销售人员必须是房地产中介机构的员工(即 Odoo 用户)。
在 Odoo 中,我们通常会引用两个模型:
res.partner:伙伴是自然人或法人实体。它可以是公司、个人,甚至是联系人地址。res.users:系统的用户。用户可以是“内部”用户,即可以访问 Odoo 后端;也可以是“门户”用户,即无法访问后端,只能访问前端(例如在电子商务中查看以往的订单)。
练习
添加买家和销售人员。
使用上文提到的两个常用模型,为 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 概念支持。
many2many 是一种双向的多重关系:一侧的任何记录都可以与另一侧的任意数量记录相关联。例如,为了在测试模型上定义指向 account.tax 模型的链接,我们可以这样写:
tax_ids = fields.Many2many("account.tax", string="Taxes")
按照惯例,many2many 字段带有 _ids 后缀。这意味着可以向测试模型添加多个税。它的行为就像记录列表,也就是说必须在循环中访问数据:
for tax in my_test_object.tax_ids:
print(tax.name)
记录列表称为 记录集,即记录的有序集合。它支持针对集合的标准 Python 操作,例如 len() 和 iter(),以及 recs1 | recs2 之类的额外集合运算。
One2many¶
参考:与本主题相关的文档可在 One2many 中找到。
注解
目标:本节结束时:
应创建新的
estate.property.offer模型,并包含相应的表单视图和列表视图。应向
estate.property模型添加报价:
在我们的房地产模块中,我们想定义房产报价的概念。房产报价是潜在买家向卖家提出的金额。报价可以低于或高于预期价格。
一个报价针对 一个 房产,但同一个房产可以有 多个 报价。这里再次出现了 many2one 概念。不过在这种情况下,我们想显示给定房产的报价列表,因此将使用 one2many 概念。
one2many 是 many2one 的反向关系。例如,我们通过 partner_id 字段在测试模型上定义了指向 res.partner 模型的链接。我们可以定义反向关系,即链接到该伙伴的测试模型列表:
test_ids = fields.One2many("test_model", "partner_id", string="Tests")
第一个参数称为 comodel,第二个参数是我们要反向的字段。
按照惯例,one2many 字段带有 _ids 后缀。它们的行为就像记录列表,也就是说必须在循环中访问数据:
for test in partner.test_ids:
print(test.name)
危险
由于 One2many 是一种虚拟关系,因此在 comodel 中 必须 定义 Many2one 字段。
练习
添加房地产房产报价数据表。
创建
estate.property.offer模型并添加以下字段:
字段 |
类型 |
属性 |
值 |
|---|---|---|---|
price |
浮动 |
||
状态 |
选择 |
不复制 |
已接受、已拒绝 |
partner_id |
Many2one ( |
required |
|
property_id |
Many2one( |
required |
创建包含
price、partner_id和status字段的列表视图和表单视图。无需创建动作或菜单。将
offer_ids字段添加到estate.property模型及其表单视图中,如本节 目标 所示。
这里有几件重要的事情需要注意。首先,并非所有模型都需要动作或菜单。有些模型只打算通过另一个模型访问。我们的练习就是这种情况:报价始终通过房产来访问。
其次,尽管 property_id 字段是必填的,我们却没有在视图中包含它。Odoo 如何知道我们的报价关联到哪个房产呢?这正是使用 Odoo 框架的神奇之处:有些东西是隐式定义的。当我们通过 one2many 字段创建记录时,为了方便起见,相应的 many2one 会被自动填充。
还撑得住吗?这一章绝对不是最轻松的一章。它引入了一些新概念,同时依赖于前面介绍的所有内容。别担心,下一章 会轻松一些 ;-)