第 7 章:模型之间的关系¶
previous chapter 涵盖了为包含基本字段的模型创建自定义视图。然而,在任何实际的业务场景中,我们都需要不止一种模型。此外,模型之间的联系是必要的。人们可以很容易地想象一个模型包含客户,另一个模型包含用户列表。您可能需要参考任何现有业务模型的客户或用户。
在我们的房地产模块中,我们需要以下房产信息:
购买该房产的客户
出售房产的房地产经纪人
房产类型:独立屋、公寓、顶层公寓、城堡……
描述该房产的标签列表:舒适、翻新……
收到的报价清单
多对一¶
参考:与此主题相关的文档可以在 Many2one 中找到。
注解
目标:在本节末尾:
应使用相应的菜单、操作和视图创建一个新的“
estate.property.type”模型。
应将三个 Many2one 字段添加到“
estate.property”模型中:属性类型、买方和卖方。
在我们的房地产模块中,我们想要定义房产类型的概念。财产类型例如是房屋或公寓。根据属性的类型对属性进行分类是标准业务需求,尤其是细化过滤。
一个属性可以有**一个**类型,但相同的类型可以分配给**多个**属性。这是由 many2one 概念支持的。
Many2one 是到另一个对象的简单链接。例如,为了在我们的测试模型中定义到“res.partner”的链接,我们可以编写:
partner_id = fields.Many2one("res.partner", string="Partner")
按照惯例,many2one 字段具有“_id”后缀。然后可以通过以下方式轻松访问合作伙伴中的数据:
print(my_test_object.partner_id.name)
其他资料
实际上,many2one 可以被视为表单视图中的下拉列表。
Exercise
添加房地产属性类型表。
创建“
estate.property.type”模型并添加以下字段:
场地 |
类型 |
属性 |
|---|---|---|
姓名 |
查尔 |
必需的 |
添加本节**目标**中显示的菜单
添加字段``property_type_id`` into your ``estate.property``模型及其表单、列表和搜索视图
本练习很好地回顾了前面的章节:您需要创建 model、设置 model、添加 action and a menu 和 create a view。
提示:不要忘记在 __init__.py, add new data files in __manifest.py__ 中导入任何新的 Python 文件或添加访问权限;-)
再次重启服务器并刷新即可看到结果!
在房地产模块中,我们想要的房产信息仍然缺少两条:买家和销售人员。买家可以是任何个人,但另一方面,销售人员必须是房地产机构的员工(即 Odoo 用户)。
在Odoo中,我们通常提到的模型有两种:
res.partner:合作伙伴是自然人或法人实体。它可以是公司、个人甚至是联系地址。res.users:系统的用户。用户可以是“内部”用户,即他们可以访问 Odoo 后端。或者他们可以是“门户”,即他们无法访问后端,只能访问前端(例如访问他们以前在电子商务中的订单)。
Exercise
添加买家和销售人员。
使用上述两个常见模型将买家和销售人员添加到“estate.property”模型中。应将它们添加到表单视图的新选项卡中,如本节的 目标 中所述。
销售人员的默认值必须是当前用户。买家不应被复制。
提示:要获取默认值,请查看下面的注释或查看示例 here。
注解
对象“self.env”可以访问请求参数和其他有用的东西:
self.env.crorself._cr是数据库*光标*对象;它用于查询数据库self.env.uidorself._uid是当前用户的数据库 IDself.env.user是当前用户的记录self.env.contextorself._context是上下文字典self.env.ref(xml_id)返回 XML id 对应的记录self.env[model_name]返回给定模型的实例
现在让我们看看其他类型的链接。
多对多¶
参考:与此主题相关的文档可以在 Many2many 中找到。
注解
目标:在本节末尾:
应使用相应的菜单和操作创建一个新的“
estate.property.tag”模型。
标签应该添加到``estate.property``模型中:
在我们的房地产模块中,我们想要定义属性标签的概念。例如,财产标签是“舒适”或“翻新”的财产。
一个属性可以有**多个**标签,并且一个标签可以分配给**多个**属性。这是由 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()`` and iter(), plus extra set operations like recs1 | recs2。
Exercise
添加房地产属性标签表。
创建“
estate.property.tag”模型并添加以下字段:
场地 |
类型 |
属性 |
|---|---|---|
姓名 |
查尔 |
必需的 |
添加本节**目标**中显示的菜单
添加字段“
tag_ids`to your ``estate.property`”模型及其表单和列表视图
提示:在视图中,使用``widget=”many2many_tags”`` attribute as demonstrated `这里<https://github.com/odoo/odoo/blob/5bb8b927524d062be32f92eb326ef64091301de1/addons/crm_iap_lead_website/views/crm_reveal_views.xml#L36>`__. The ``widget``属性将在:doc:`a later chapter of the training <11_sprinkles>`中详细解释。现在,您可以尝试添加和删除它并查看结果;-)
一对多¶
参考:与此主题相关的文档可以在 One2many 中找到。
注解
目标:在本节末尾:
应使用相应的表单和列表视图创建一个新的“
estate.property.offer”模型。优惠应添加到“
estate.property”模型中:
在我们的房地产模块中,我们想要定义房地产报价的概念。房产报价是潜在买家向卖家提供的金额。报价可能低于或高于预期价格。
优惠适用于**一个**房产,但同一房产可以有**多个**优惠。 many2one**的概念再次出现。但是,在本例中,我们想要显示给定属性的报价列表,因此我们将使用 **one2many 概念。
one2many 是 Many2one 的逆。例如,我们在测试模型上定义了一个指向“res.partner` model thanks to the field ``partner_id`”的链接。我们可以定义逆关系,即链接到我们合作伙伴的测试模型列表:
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 字段。
Exercise
添加房地产报价表。
创建“
estate.property.offer”模型并添加以下字段:
场地 |
类型 |
属性 |
价值观 |
|---|---|---|---|
价格 |
漂浮 |
||
地位 |
选择 |
没有副本 |
接受、拒绝 |
合作伙伴_id |
Many2one ( |
必需的 |
|
属性_id |
Many2one ( |
必需的 |
这里有几件重要的事情需要注意。首先,我们不需要所有模型的操作或菜单。某些模型只能通过另一个模型访问。我们的练习中就是这种情况:报价始终是通过属性访问的。
其次,尽管“property_id”字段是必需的,但我们没有将其包含在视图中。 Odoo 如何知道我们的报价与哪个房产相关?这就是使用 Odoo 框架的神奇之处:有时事物是隐式定义的。当我们通过one2many字段创建记录时,为了方便起见,会自动填充相应的many2one。
还活着吗?这一章绝对不是最简单的一章。它引入了一些新概念,同时依赖于之前引入的所有内容。 next chapter 会更轻,不用担心;-)