第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 ( |
必須 |
|
プロパティ id |
Many2one ( |
必須 |
price
とpartner_id
とstatus
フィールドを持つリストビューとフォームビューを作成します。アクションやメニューを作成する必要はありません。このセクションの 目標 に示されているように、
emate.property
モデルとそのフォームビューにフィールドoffer_ids
を追加します。
ここでは、いくつかの重要な点に注目してください。まず、すべてのモデルにアクションやメニューが必要なわけではありません。モデルの中には、他のモデルを介してのみアクセスされるように意図されているものもあります。今回の練習問題では、オファーは常に物件を介してアクセスされるというケースです。
次に、 property_id
フィールドが必須であるにもかかわらず、ビューにそれを含めませんでした。オファーがどのプロパティにリンクされているか、Odooはどうやって知るのでしょうか?これは、Odooフレームワークを使用する際のマジックの一部です。one2manyフィールドでレコードを作成すると、便宜的に、対応するmany2oneが自動入力されます。
まだ生きていますか? この章は間違いなく最も簡単なものではありません。以前に紹介されたすべてのものに頼りながら、いくつかの新しい概念を紹介しました。 next chapter は軽くなります。心配しないでください;-)