AI翻译及测试Odoo17开发教程,第七章:模型间的关系

Chapter 7: Relations Between Models
第七章:模型间的关系

原文来自:
https://www.odoo.com/documentation/17.0/zh_CN/developer/tutorials/server_framework_101/07_relations.html
使用通义千问翻译。

测试代码:https://gitee.com/zhang-wei918/estate

The previous chapter covered the creation of custom views for a model containing basic fields. However, in any real business scenario we need more than one model. Moreover, links between models are necessary. One can easily imagine one model containing the customers and another one containing the list of users. You might need to refer to a customer or a user on any existing business model.
上一章介绍了为包含基本字段的模型创建自定义视图。然而,在任何实际的商业场景中,我们都需要不止一个模型。而且,模型之间的关联是必要的。很容易想象,一个模型包含客户信息,另一个模型包含用户列表。你可能需要在任何现有的业务模型中引用客户或用户。

In our real estate module, we want the following information for a property:
在我们的房地产模块中,我们希望为一处房产提供以下信息:

  • the customer who bought the property
    购买该房产的客户
  • the real estate agent who sold the property
    出售该房产的房地产经纪人
  • the property type: house, apartment, penthouse, castle…
    房产类型:别墅、公寓、顶层豪华公寓、城堡等
  • a list of tags characterizing the property: cozy, renovated…
    描述房产的一系列标签:舒适、翻新过…
  • a list of the offers received 收到的一系列报价
    收到的一系列报价

Many2one 多对一

Reference: the documentation related to this topic can be found in Many2one.
参考: 相关于此主题的文档可以在“Many2one”中找到。

 注解

Goal: at the end of this section: 目标: 在本节结束时,应完成以下任务:

  • a new estate.property.type model should be created with the corresponding menu, action and views.
    创建一个新的estate.property.type模型,并配备相应的菜单、操作和视图。

Property type

  • tags should be added to the estate.property model:

Property

In our real estate module, we want to define the concept of property type. A property type is, for example, a house or an apartment. It is a standard business need to categorize properties according to their type, especially to refine filtering.
在房地产模块中,我们需要定义房产类型的概念。例如,房产类型可以是别墅或公寓。根据类型对房产进行分类是一种标准的商业需求,特别是为了细化过滤条件。

A property can have one type, but the same type can be assigned to many properties. This is supported by the many2one concept.
一处房产可以有一个类型,但同一类型可以分配给多处房产。这种关系由许多对一(many2one)概念支持。

A many2one is a simple link to another object. For example, in order to define a link to the res.partner in our test model, we can write:
多对一(many2one)是一个指向另一个对象的简单链接。例如,为了在测试模型中定义到res.partner的链接,我们可以这样写:

partner_id = fields.Many2one("res.partner", string="Partner")

By convention, many2one fields have the _id suffix. Accessing the data in the partner can then be easily done with:
按照惯例,多对一字段名后缀带有 _id。之后,访问该伙伴对象的数据变得很简单,例如:

print(my_test_object.partner_id.name)

 参见

foreign keys 外键

In practice a many2one can be seen as a dropdown list in a form view.
实际上,许多对一字段在表单视图中表现为下拉选择列表。

 Exercise

Add the Real Estate Property Type table. 添加房地产类型表

  • Create the estate.property.type model and add the following field:
    创建estate.property.type模型,并添加以下字段
FieldTypeAttributes
nameCharrequired
  • Add the menus as displayed in this section’s Goal
    根据本节目标添加菜单。
  • Add the field property_type_id into your estate.property model and its form, tree and search views
    estate.property模型中添加property_type_id字段,并在表单视图、列表视图和搜索视图中显示它。


This exercise is a good recap of the previous chapters: you need to create a model, set the model, add an action and a menu, and create a view.
此练习是对前几章节内容的良好回顾:你需要创建一个模型,定义模型,添加操作和菜单,以及创建视图。

Tip: do not forget to import any new Python files in __init__.py, add new data files in __manifest.py__ or add the access rights 😉
提示:不要忘记在__init__.py中导入任何新的Python文件,在__manifest__.py中添加新的数据文件,或添加访问权限。

Once again, restart the server and refresh to see the results!
再次重启服务器并刷新页面以查看结果!

In the real estate module, there are still two missing pieces of information we want on a property: the buyer and the salesperson. The buyer can be any individual, but on the other hand the salesperson must be an employee of the real estate agency (i.e. an Odoo user).
在房地产模块中,针对一处房产仍有两项信息缺失:买家和销售人员。买家可以是任何人,而销售人员必须是房地产代理机构的员工(即Odoo用户)。

In Odoo, there are two models which we commonly refer to:
在Odoo中,有两个我们常引用的模型:

  • res.partner: a partner is a physical or legal entity. It can be a company, an individual or even a contact address.
    res.partner:伙伴可以是实体或法人,它可以是公司、个人,甚至是联系地址。
  • res.users: the users of the system. Users can be ‘internal’, i.e. they have access to the Odoo backend. Or they can be ‘portal’, i.e. they cannot access the backend, only the frontend (e.g. to access their previous orders in eCommerce).
    res.users:系统用户。用户可以是“内部”用户,即他们可以访问Odoo后台;或者是“门户”用户,即他们无法访问后台,只能访问前端(例如,在电子商务中查看他们的历史订单)。

 Exercise

Add the buyer and the salesperson. 添加买家和销售人员

Add a buyer and a salesperson to the estate.property model using the two common models mentioned above. They should be added in a new tab of the form view, as depicted in this section’s Goal.
使用上述两个通用模型,在estate.property模型中添加买家和销售人员字段,它们应在表单视图的新标签页中显示,如本节目标所示。

The default value for the salesperson must be the current user. The buyer should not be copied.
销售人员的默认值应设为当前用户。买家信息不应被复制。

Tip: to get the default value, check the note below or look at an example here.
提示:要设置默认值,请参考下方注释或查看此处的示例。

 注解

The object self.env gives access to request parameters and other useful things:
self.env对象提供了对请求参数和其他有用信息的访问:

  • self.env.cr or self._cr is the database cursor object; it is used for querying the database
    self.env.crself._cr 是数据库游标对象,用于查询数据库。
  • self.env.uid or self._uid is the current user’s database id
    self.env.uidself._uid 是当前用户的数据库ID。
  • self.env.user is the current user’s record
    self.env.user 是当前用户的记录。
  • self.env.context or self._context is the context dictionary
    self.env.contextself._context 是上下文字典。
  • self.env.ref(xml_id) returns the record corresponding to an XML id
    self.env.ref(xml_id) 返回与XML ID对应的记录
  • self.env[model_name] returns an instance of the given model
    self.env[model_name] 返回给定模型的实例

Now let’s have a look at other types of links.
接下来,我们将探讨其他类型的关联

Many2many 多对多

Reference: the documentation related to this topic can be found in Many2many.
参考:与这一主题相关的文档可以在多对多关系(Many2many)部分找到。

 注解

Goal: at the end of this section: 目标:在本节结束时

  • a new estate.property.tag model should be created with the corresponding menu and action.
    应该创建一个新的 estate.property.tag模型,并附带相应的菜单和操作。

Property tag

  • tags should be added to the estate.property model: 应将标签添加至 estate.property.tag

Property

In our real estate module, we want to define the concept of property tags. A property tag is, for example, a property which is ‘cozy’ or ‘renovated’.
在我们的房地产模块中,我们想要定义属性标签的概念。例如,“温馨”或“已翻新”的属性就是一种属性标签。

A property can have many tags and a tag can be assigned to many properties. This is supported by the many2many concept.
一个属性可以有多个标签,而一个标签也可以被分配给多个属性。这正是通过多对多概念来支持的。

A many2many is a bidirectional multiple relationship: any record on one side can be related to any number of records on the other side. For example, in order to define a link to the account.tax model on our test model, we can write:
多对多是一种双向多重关系:任一侧的任意记录可以与另一侧的任意数量的记录相关联。例如,为了在我们的测试模型上定义与账户税模型的链接,我们可以这样写:

tax_ids = fields.Many2many("account.tax", string="Taxes")

By convention, many2many fields have the _ids suffix. This means that several taxes can be added to our test model. It behaves as a list of records, meaning that accessing the data must be done in a loop:
按照惯例,多对多字段带有_ids后缀。这意味着可以向我们的测试模型添加多个税项。它表现得像一个记录列表,这意味着访问数据时必须使用循环:

for tax in my_test_object.tax_ids:
    print(tax.name)

A list of records is known as a recordset, i.e. an ordered collection of records. It supports standard Python operations on collections, such as len() and iter(), plus extra set operations like recs1 | recs2.
记录列表被称为记录集,即有序的记录集合。它支持Python集合上的标准操作,如len()和iter(),以及额外的集合操作,如recs1 | recs2。

 Exercise

Add the Real Estate Property Tag table. 添加房地产属性标签表。

  • Create the estate.property.tag model and add the following field:
    创建estate.property.tag模型并添加以下字段:
FieldTypeAttributes
nameCharrequired
  • Add the menus as displayed in this section’s Goal 添加如本节目标所示的菜单。
  • Add the field tag_ids to your estate.property model and in its form and tree views
    在你的estate.property模型中添加tag_ids字段,并在它的表格和树状视图中添加。

Tip: in the view, use the widget="many2many_tags" attribute as demonstrated here. The widget attribute will be explained in detail in a later chapter of the training. For now, you can try to adding and removing it and see the result 😉
小贴士:在视图中,使用widget=”many2many_tags”属性,如下面的例子所示。Widget属性将在训练的后续章节中详细解释。现在,你可以尝试添加和删除它,看看结果如何。;-)

One2many 一对多

Reference: the documentation related to this topic can be found in One2many.
参考:关于此主题的相关文档可在一对一多(One2many)中找到

 注解

Goal: at the end of this section: 目标:在本节结束时:

  • a new estate.property.offer model should be created with the corresponding form and tree view.
    应创建一个新的estate.property.offer模型,并附带相应的表格和树状视图。
  • offers should be added to the estate.property model:
    报价应被添加至estate.property模型:

Property offers

In our real estate module, we want to define the concept of property offers. A property offer is an amount a potential buyer offers to the seller. The offer can be lower or higher than the expected price.
在我们的房地产模块中,我们想要定义房地产报价的概念。房地产报价是潜在买家向卖家提出的金额。报价可能低于或高于预期价格。

An offer applies to one property, but the same property can have many offers. The concept of many2one appears once again. However, in this case we want to display the list of offers for a given property so we will use the one2many concept.
一个报价适用于一个特定的房产,但同一房产可以有多个报价。再次出现了多对一的概念。然而,在这种情况下,我们想要展示针对某一特定房产的所有报价列表,因此我们将使用一对多的概念。

A one2many is the inverse of a many2one. For example, we defined on our test model a link to the res.partner model thanks to the field partner_id. We can define the inverse relation, i.e. the list of test models linked to our partner:
一对多是多对一的反向。例如,我们在测试模型上定义了与res.partner模型的链接,通过partner_id字段实现。我们可以定义反向关系,即与我们合作伙伴相关的测试模型列表:

test_ids = fields.One2many("test_model", "partner_id", string="Tests")

The first parameter is called the comodel and the second parameter is the field we want to inverse.
第一个参数称为协模型(comodel),第二个参数是我们要反转的字段。

By convention, one2many fields have the _ids suffix. They behave as a list of records, meaning that accessing the data must be done in a loop:
按照惯例,一对多字段带有_ids后缀。它们表现得像一个记录列表,这意味着访问数据时必须通过循环进行:

for test in partner.test_ids:
    print(test.name)

 危险

Because a One2many is a virtual relationship, there must be a Many2one field defined in the comodel.
由于一对多是一种虚拟关系,必须在协模型中定义一个多对一字段。

 Exercise

Add the Real Estate Property Offer table. 添加房地产报价表。

  • Create the estate.property.offer model and add the following fields:
    创建estate.property.offer模型并添加以下字段:
FieldTypeAttributesValues
priceFloat
statusSelectionno copyAccepted, Refused
partner_idMany2one (res.partner)required
property_idMany2one (estate.property)required
  • Create a tree view and a form view with the pricepartner_id and status fields. No need to create an action or a menu.
    创建包含price、partner_id和status字段的树状视图和表格视图。无需创建动作或菜单。
  • Add the field offer_ids to your estate.property model and in its form view as depicted in this section’s Goal.
    在你的estate.property模型中添加offer_ids字段,并在其表格视图中添加,如本节目标中所示。

There are several important things to notice here. First, we don’t need an action or a menu for all models. Some models are intended to be accessed only through another model. This is the case in our exercise: an offer is always accessed through a property.
这里有几点重要的事情需要注意。首先,并非所有模型都需要动作或菜单。某些模型仅旨在通过另一个模型访问。正如在我们的练习中一样:报价总是通过房产访问的。

Second, despite the fact that the property_id field is required, we did not include it in the views. How does Odoo know which property our offer is linked to? Well that’s part of the magic of using the Odoo framework: sometimes things are defined implicitly. When we create a record through a one2many field, the corresponding many2one is populated automatically for convenience.
其次,尽管property_id字段是必填的,但我们并没有在视图中包含它。Odoo是如何知道我们的报价与哪个房产相关联的呢?这正是使用Odoo框架的神奇之处:有些事情是隐式定义的。当我们通过一对一多字段创建记录时,为了方便,对应的多对一字段会被自动填充。

Still alive? This chapter is definitely not the easiest one. It introduced a couple of new concepts while relying on everything that was introduced before. The next chapter will be lighter, don’t worry 😉
你还在吗?这一章绝对不是最轻松的。它引入了一些新概念,同时依赖于之前介绍的所有内容。不用担心,下一章将会更轻松些。


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注