前言
上一章介绍了自定义的创建 包含基本字段的模型的视图。但是,在任何实际业务场景中,我们需要的不仅仅是 一个模型。此外,模型之间的链接是必要的。人们可以很容易地想象一个模型包含 客户和另一个包含用户列表的客户。您可能需要推荐客户 或任何现有商业模式的用户。
在我们的房地产模块中,我们需要房产的以下信息:
-
购买房产的客户
-
出售房产的真正重述经纪人
-
物业类型:洋房、公寓、顶层公寓、城堡...
-
该物业的特征标签列表:舒适,翻新...
-
收到的报价列表
Many2one(多对一)
class odoo.fields.Many2one
这样一个字段的值是一个大小为0(没有记录)或1(单个记录)的记录集。
参数:
-
comodel_name (str) -目标型号名称必选,相关字段或扩展字段除外。
-
domain 一个可选的域,可以在客户端的候选值上设置(域或将被计算以提供域的python表达式)
-
context (dict)------在客户端处理该字段时使用的可选上下文
-
ondelete (str) -当引用的记录被删除时做什么;可能的值是:'set null', 'restrict', 'cascade'
-
auto_join (bool) -在搜索该字段时是否生成join(默认:False)
-
delegate (bool) -将其设置为True以使目标模型的字段可以从当前模型访问(对应于_inherits)
-
check_company(bool) -在_check_company()中标记要验证的字段。根据字段属性添加默认公司域。
目标:
- 应使用相应的菜单、操作和视图创建一个新模型
-三个Many2one 字段应该被添加到 estate.property 模型: 属性 type(类型), buyer(买家) 和seller(卖家)
在房地产模块中,我们要定义属性类型的概念。例如,房产类型是房子或公寓。根据属性的类型对属性进行分类是一种标准的业务需求,尤其是在细化过滤时。
一个属性可以有一个类型,但是相同的类型可以分配给许多属性。这得到了many2one(多对一)概念的支持。
many2one 是指向另一个对象的简单链接。例如,为了在我们的测试模型中定义到res.partner 的链接,我们可以这样写:
python
partner_id = fields.Many2one("res.partner", string="Partner")
按照惯例,许多字段都有_id后缀。然后可以很容易地通过以下方式访问合作伙伴(partner)中的数据:
python
print(my_test_object.partner_id.name)
在实践中,many2one 可以看作是窗体视图中的下拉列表。
在房地产模块中,我们仍然缺少两条关于房产的信息: 买方和销售人员。买方可以是任何个人,但另一方面 销售人员必须是房地产中介的雇员(即Odoo用户)。
在Odoo中,我们通常指的是两种模型:
-
res.partner:合作伙伴是自然人或法人实体。它可以是公司、个人或 甚至是联系地址。
-
res.users:系统的用户。用户可以是"内部的",即他们有 访问 Odoo 后端。或者它们可以是"门户",即它们无法访问后端,只能访问 前端(例如,在电子商务中访问他们以前的订单)。
注意
self.env对象允许访问请求参数和其他有用的东西:
-
self.env.cr 或self.cr 是数据库游标对象;用于查询数据库
-
self.env.uid 或self._uid 是当前用户的数据库id
-
self.env.user 是当前用户的记录
-
self.env.context 或者self._context 是上下文字典
-
self.env.ref(xml_id) 返回与XML id对应的记录
-
self.env[model_name] 返回给定模型的实例
Many2many (多对多)
class odoo.fields.Many2many[source]
Many2many 字段的值是一个记录集.
参数:
comodel_name -- 目标模型的名称(字符串)必选,相关或扩展字段除外
relation (str) -- 在数据库中存储关系的表的可选名称
column1 (str) -- 引用表中"这些"记录的列的可选名称
column2 (str) -- 引用表关系中"那些"记录的列的可选名称
属性relation, column1和column2是可选的。如果没有给出,则从模型名自动生成名称,只要model_name和comodel_name不同!
请注意,在具有相同模型的给定模型上有几个具有隐式关系参数的字段是不被ORM接受的,因为这些字段将使用相同的表。ORM防止两个many2many字段使用相同的关系参数,除非:
-
两个字段使用相同的模型,模型和关系参数是显式的
-
至少有一个字段属于**_auto = False** 的模型
domain -- 一个可选的域,在客户端的候选值上设置(域或一个python表达式,将被计算以提供域)
context (dict) -- 在处理该字段时在客户端使用的可选上下文
check_company (bool) -- 在_check_company()中标记要验证的字段。根据字段属性添加默认公司域。
目标
- 应该用相应的菜单和操作创建一个新的estate.property.tag 模型。
- 标签添加到 estate. property 模型中:
在我们的不动产模块中,我们想要定义属性标签的概念。例如,属性标签是"舒适(cozy)"或"翻新(renovated)"的属性。
一个属性可以有多个标签,一个标签可以分配给多个属性。这得到了多对多概念的支持。
many2many是一种双向多重关系: 一端的任何记录都可以与另一端的任意数量的记录相关联。例如,为了定义到帐户的链接。在我们的测试模型上,我们可以这样写:
python
tax_ids = fields.Many2many("account.tax", string="Taxes")
按照惯例,many2many字段具有_ids后缀。这意味着几个税可以添加到我们的测试模型中。它的行为就像一个记录列表,这意味着访问数据必须在循环中完成:
python
for tax in my_test_object.tax_ids:
print(tax.name)
记录列表称为记录集,即记录的有序集合。它支持对集合的标准Python操作,如len()和iter(),以及额外的集合操作,如recs1 | recs2。
One2many(一对多)
class odoo.fields.One2many [source]
One2many字段;该字段的值是comodel_name中所有记录的记录集,使得字段inverse_name等于当前记录。
参数:
comodel_name (str) -- 目标模型的名称
inverse_name (str) -- 目标模型中反向Many2one字段的名称
domain -- 一个可选的域,在客户端的候选值上设置(域或一个python表达式,将被计算以提供域)
context (dict) -- 在处理该字段时在客户端使用的可选上下文
auto_join (bool) -- 是否在搜索该字段时生成join (默认值:False)
- comodel_name和inverse_name属性为必选项,相关字段或字段扩展除外。
目标
-
应该用相应的表单和树视图创建一个新的estate.property.offer模型。
-
offers 应该加到estate.property 模型:
在我们的房地产模块中,我们要定义房地产报价的概念。物业报价是潜在买家向卖家提供的金额。报价可以低于预期价格,也可以高于预期价格。
一个报价适用于一个物业,但同一物业可以有多个报价。many2one 的概念再次出现。但是,在本例中,我们希望显示给定属性的报价列表,因此我们将使用one2many 概念。
one2many是many2one的反转。例如,我们在测试模型中定义了一个指向res.partner模型的链接,这要归功于partner_id字段。我们可以定义反转关系,即链接到我们的合作伙伴的测试模型列表:
python
test_ids = fields.One2many("test_model", "partner_id", string="Tests")
第一个参数称为 目标模型,第二个参数是目标模型的目标字段。
按照约定,one2many 字段的后缀是_ids ,它们表现为一个记录列表,这意味着访问数据必须在一个循环中完成:
python
for test in partner.test_ids:
print(test.name)
注意
因为 One2many 是一个虚拟关系,所以在 目标模型 中必须定义一个 Many2one 字段。
使用Odoo框架的神奇之处在于:有时事情是隐式定义的。当我们通过one2many字段创建记录时,相应的many2one会自动填充以方便使用