原文:Odoo 18 官方开发教程“Server framework 101”第 7 章。本文尽量保留原文结构、代码、练习与图片,仅进行中文翻译,并在文末增加“老赵解读”。
第7章:模型之间的关系
上一章 涵盖了自定义的创建
包含基本字段的模型视图。然而,在任何实际的业务场景中,我们需要的不仅仅是
一个模型。此外,模型之间的链接是必要的。人们可以很容易地想象一个模型包含
客户和另一个包含用户列表的。您可能需要推荐一位客户
或任何现有业务模型的用户。
在我们的房地产模块中,我们需要房产的以下信息:
- 购买房产的顾客
- 出售房产的房地产经纪人
- 房产类型:房屋、公寓、顶层公寓、城堡……
- 描述房产的标签列表:舒适、翻新……
- 收到的报价列表
Many2one
参考:与该主题相关的文档可以在以下位置找到
Many2one。
说明
目标: 在本节末尾:
- 应使用相应的菜单、操作和视图创建新的
estate.property.type模型。
- 三个Many2one字段应添加到
estate.property模型:房产类型,买方和卖方。
在我们的房地产模块中,我们要定义房产类型的概念。房产型
例如,是房屋或公寓。这是一个标准的业务需要分类
房产根据其类型,特别进行细化过滤。
房产可以有 一 类型,但可以分配相同的类型 许多 房产。
这是由 多对一 概念。
Many2one 是到另一个对象的简单链接。例如,为了定义一个链接到
res.partner 在我们的测试模型中,我们可以这样写:
partner_id = fields.Many2one("res.partner", string="Partner")
按照惯例,many2one字段具有 _id 后缀。访问合作伙伴中的数据
然后可以轻松完成:
print(my_test_object.partner_id.name)
另请参阅
实际上,many2one 可以被视为表单视图中的下拉列表。
练习
添加房地产房产类型表。
- 创建
estate.property.type模型并添加以下字段:
字段 类型 属性 姓名 Char 必填
- 添加本节中显示的菜单 目标
- 将字段
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模型:
在我们的房地产模块中,我们想要定义房产标签的概念。房产标签
例如,房产表示“舒适”或“翻新”。
房产可以有 许多 标签和标签可以分配给 许多 房产。
这是由 多对多 概念。
多对多是一种双向多重关系:一侧的任何记录都可以与任何
另一侧的记录的编号。例如,为了定义一个链接到
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 的操作。
练习
添加房地产房产标签表。
- 创建
estate.property.tag模型并添加以下字段:
字段 类型 属性 姓名 Char 必填
- 添加本节中显示的菜单 目标
- 将字段
tag_ids添加到estate.property模型及其表单和列表视图中提示:在视图中,使用
widget="many2many_tags"属性,如所示
这里。
widget属性将在 培训的后续章节 中详细解释。
现在,您可以尝试添加和删除它并查看结果;-)
One2many
参考:与该主题相关的文档可以在以下位置找到
One2many。
说明
目标: 在本节末尾:
- 应使用相应的表单和列表视图创建新的
estate.property.offer模型。- 报价应添加到
estate.property模型:
在我们的房地产模块中,我们想要定义房产报价的概念。房产报价
是潜在买家报价向卖家支付的金额。报价可以低于或高于
预期价格。
报价适用于 一 房产,但相同的房产可以有 许多 报价。
的概念 多对一 再次出现。但是,在本例中我们想要显示列表
对于给定的房产的报价因此我们将使用 一对多 概念。
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模型并添加以下字段:
字段 类型 属性 价值观 价格 Float 状态 Selection 没有副本 接受、拒绝 合作伙伴_id Many2one ( res.partner)必填 属性_id Many2one ( estate.property)必填
- 使用
price、partner_id和status字段创建列表视图和表单视图。否
需要创建一个操作或菜单。- 将字段
offer_ids添加到estate.property模型并在其表单视图中作为
本节中描述的 目标.
这里有几件重要的事情需要注意。首先,我们不需要所有操作或菜单
模型。某些模型只能通过另一个模型访问。我们的情况就是这样
练习:报价始终通过房产访问。
其次,尽管 property_id字段是必需的,但我们没有将其包含在
意见。 Odoo 如何知道我们的报价链接到哪个房产?嗯,这是其中的一部分
使用 Odoo 框架的魔力:有时事物是隐式定义的。当我们创建
一个记录通过一个one2many字段,对应的many2one会自动填充
为了方便。
还活着吗?这一章绝对不是最简单的一章。它引入了几个新概念
同时依赖之前介绍的一切。的
下一章 会更轻,不用担心;-)
老赵解读
Many2one、One2many 和 Many2many 是把孤立数据组织成业务网络的基础。关系字段不仅决定界面上的选择和明细,也直接影响查询性能、删除策略和数据一致性。
建模时要先判断关系的所有权:谁是主记录、谁依附于谁、删除主记录后明细应保留还是级联删除。把这些规则写进模型,比依赖使用者记住操作规范更可靠。