第7章:モデル間のリレーション

:doc:`前の章<06_basicviews>は、基本フィールドを含むモデルのカスタムビューの作成をカバーしました。 しかし、実際のビジネスシナリオでは、複数のモデルが必要です。 また、モデル間のリンクが必要であり、顧客を含むモデルとユーザーのリストを含むモデルを容易に想像することができます。 既存のビジネスモデルで顧客またはユーザーを参照する必要があるかもしれません。

この不動産モジュールでは、物件について以下の情報が必要です。

  • その物件を購入した顧客

  • 不動産を売却した不動産業者は

  • 物件の種類:家、アパート、ペントハウス、お城...

  • 物件を特徴づけるタグのリスト:居心地が良い、改装されている...

  • 受け取ったオファーのリスト

Many2one

参考: このトピックに関連するドキュメントは、 Many2one にあります。

注釈

目標: このセクションの最後には、

  • 新しい estate.property.type モデルが作成され、対応するメニュー、アクション、ビューも作成されています。

プロパティの種類
  • estate.property モデルに物件タイプ(type)、買い手(buyer)、売り手(seller)といった3つのMany2oneフィールドが追加されています。

属性

不動産モジュールにおいて、物件タイプの概念を定義したいと考えています。物件タイプとは、例えば、家やアパートなどのことです。ビジネスでは、物件をタイプ別に分類することが標準的なニーズであり、特にフィルタリングを洗練させることが重要です。

1つの物件は 1つの タイプを持つことができますが、同じタイプを 多くの 物件に割り当てることができます。これは、 many2one という概念によってサポートされています。

Many2oneは、他のオブジェクトへの単純なリンクです。例えば、テストモデルの res.partner へのリンクを定義するためには、次のように書きます。

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

慣例上、many2oneフィールドには _id という接尾辞が付きます。パートナー(partner)のデータへのアクセスは、次のように簡単に行うことができます。

print(my_test_object.partner_id.name)

関連項目

外部キー

実際には、many2oneはフォームビューのドロップダウンリストのようにみえます。

Exercise

不動産物件の種類テーブルを追加してみましょう。

  • estate.property.type モデルを作成し、次のフィールドを追加します

フィールド

属性

名前(name)

文字

必須

  • このセクションの 目標 に示したメニューを追加します

  • 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.

ヒント: __init__.py で新しい Python ファイルをインポートすること、 __manifest__.py で新しいデータファイルを追加すること、また、アクセス権限を追加することを忘れないでください ;-)

もう一度、サーバーを再起動して、結果を確認しましょう。

不動産モジュールでは、物件について必要な情報のうち、買い手と販売員の2つの情報がまだ欠けています。購入者は個人でも構いませんが、販売員は不動産会社の従業員(つまりOdooユーザー) でなければなりません。

Odooでは一般的に参照できる2つのモデルがあります。

  • res.partner: パートナーは物理的または法的なエンティティです。会社、個人、または連絡先アドレスにすることができます。

  • res.users: システムのユーザ。ユーザを internal にすることができます。つまり、Odoo バックエンドにアクセスできます。 あるいは、 portal にすることもできます。すなわち、バックエンドにはアクセスできません。フロントエンドのみ(例えば、eコマースで以前の注文にアクセスするなど) です。

Exercise

買い手(buyer)と販売員(salesperson)を追加してみましょう。

前述の2つの共通モデルを使って、 estate.property モデルに買い手(buyer)と販売員(salesperson)を追加してください。これらは、このセクションの 目標 に示されているように、フォームビューの新しいタブに追加されなければなりません。

販売員のデフォルト値は現在のユーザーとします。購入者はコピーされないようにしてください。

ヒント: デフォルト値を取得するには、次の注釈を確認するか、こちら の例を見てください。

注釈

オブジェクト self.env は、リクエストパラメータやその他の有用なものへのアクセスを提供します。

  • self.env.cr または self._cr はデータベースの cursor オブジェクトです。データベースへの問い合わせに使用されます。

  • 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] は与えられたモデルのインスタンスを返します。

では、他のリンクタイプについても見てみましょう。

Many2multi(多数)

参考: このトピックに関連するドキュメントは、 Many2many にあります。

注釈

目標: このセクションの最後には、

  • 新しい estate.property.tag モデルが対応するメニューとアクションと共に作成されています。

プロパティタグ
  • タグが estate.property モデルに追加されています。

属性

この不動産モジュールにおいて、物件タグの概念を定義したいと考えています。物件タグとは、例えば、「居心地が良い( 'cozy' )」や「改装されている( 'renovated' )」などの物件のことです。

1つの物件は 多くの タグを持つことができ、1つのタグを 多くの 物件に割り当てることができます。これを支えるのが、 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)

レコードのリストは レコードセット と呼ばれ、順序付けられたレコードの集合体です。レコードセットは len()iter() といった Python の標準的なコレクション操作に加え、 recs1 | recs2 といった追加のセット操作もサポートしています。

Exercise

Real Estate Property Tagテーブルを追加してみましょう。

  • estate.property.tag モデルを作成し、次のフィールドを追加します。

フィールド

属性

名前(name)

文字

必須

  • このセクションの 目標 に示したメニューを追加します

  • 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 ;-)

One2covery

参考: このトピックに関連するドキュメントは、 One2many にあります。

注釈

目標: このセクションの最後には、

  • 新しい``estate.property.offer`` モデルは、対応するフォームとリストビューで作成する必要があります。

  • オファーは estate.property モデルに追加されるようにします。

プロパティオファー

不動産モジュールにおいて、物件オファーの概念を定義したいと思います。物件オファーとは、買い手候補が売り手に提示する金額のことです。オファーは、想定価格より低くても高くても構いません。

オファーは 1つの 物件に適用されますが、同じ物件に 多くの オファーがある場合もあります。 Many2one の概念が再び登場しました。しかし、今回は、ある物件のオファーのリストを表示したいので、 one2many の概念を使います。

One2manyはmany2oneの逆です。例えば、テストモデルでは、フィールド partner_id を使って res.partner モデルへのリンクを定義しました。逆の関係、つまりパートナーにリンクされたテストモデルのリストを定義することができます。

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

最初のパラメータは comodel と呼ばれ、2 番目のパラメータは逆引きしたいフィールドです。

慣例上、one2many のフィールドには _ids という接尾辞が付きます。これらのフィールドはレコードのリストとして動作するため、データへのアクセスはループ処理で行う必要があります。

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

危険

One2many は仮想的なリレーションシップですので、comodel には Many2one フィールドを定義 しなければなりません

Exercise

Real Estate Property Offer テーブルを追加してみましょう。

  • estate.property.offer モデルを作成し、次のフィールドを追加します。

フィールド

属性

価格

フロート

状態

選択

コピーしない

承認、拒否

partner_id

Many2one (res.partner)

必須

プロパティ id

Many2one (estate.property)

必須

  • pricepartner_idstatus フィールドを持つリストビューとフォームビューを作成します。アクションやメニューを作成する必要はありません。

  • このセクションの 目標 に示されているように、 emate.property モデルとそのフォームビューにフィールド offer_ids を追加します。

ここでは、いくつかの重要な点に注目してください。まず、すべてのモデルにアクションやメニューが必要なわけではありません。モデルの中には、他のモデルを介してのみアクセスされるように意図されているものもあります。今回の練習問題では、オファーは常に物件を介してアクセスされるというケースです。

次に、 property_id フィールドが必須であるにもかかわらず、ビューにそれを含めませんでした。オファーがどのプロパティにリンクされているか、Odooはどうやって知るのでしょうか?これは、Odooフレームワークを使用する際のマジックの一部です。one2manyフィールドでレコードを作成すると、便宜的に、対応するmany2oneが自動入力されます。

まだ生きていますか? この章は間違いなく最も簡単なものではありません。以前に紹介されたすべてのものに頼りながら、いくつかの新しい概念を紹介しました。 next chapter は軽くなります。心配しないでください;-)