はじめに
Odooのデータ構造を扱っていると、別モデルにある値をわざわざ画面を移動して見に行かせず、現在のフォーム上にそのまま表示したい場面が頻繁に出てきます。Relatedフィールドは、そのニーズに対してOdooが用意したシンプルで宣言的な解決手段です。
計算フィールドとしてPythonコードを書く代わりに、Relatedフィールドは既存のリレーションをたどって最終的な値をそのまま表示します。開発者向けにも便利ですが、Odoo Studioを利用する業務コンサルタントでもコードを書かずに利用できるため、現場での効率化に非常に役立ちます。
本稿では、Relatedフィールドが何を保持するのか、Odooの内部でどのように動くのか、StudioやPythonでの作成方法、そして実務でどのように活用されるかを解説します。
OdooのRelatedフィールドとは何か
OdooのORMでは、RelatedはFloatやCharのような独立した型というよりは、別モデルのフィールドを参照して“そのまま見せる”ための近道です。つまり、Relatedはチェーンの終端にあるフィールドの型を引き継いで表示します。
例えば受注書(sale.order)が顧客を指すpartner_idを持っているとき、related='partner_id.country_id'と指定すれば受注フォーム上に顧客の国をそのまま表示できます。別途値を複製して持つ必要はありません。
ユーザーから見ると、Relatedフィールドは通常のフォームの入力項目と変わりません。終端フィールドが文字列型ならテキスト入力、Many2oneならドロップダウン、Booleanならチェックボックスとしてレンダリングされ、見た目は参照先のフィールドに合わせて表示されます。
初期設定ではRelatedフィールドは読み取り専用かつデータベースに保存されません。そのため常に参照元の最新値を反映しますが、検索やドメインで使いたい場合はstore=Trueにする必要があります。
Odoo Studioでのフィールド追加時にRelatedフィールドを選べば、既存のリレーションを辿るパスを指定するだけでフィールドが作られます。コードを書かずにフォームを充実させたいコンサルタントにとって非常に実用的な機能です。
Relatedフィールドの仕組み
Relatedフィールドを読み取る際はドットで区切られたチェーンを辿ります。チェーン中の各ステップ(末端を除く)はリレーション型(Many2one/One2many/Many2many)である必要があり、末端は任意の型で構いません。
以下はPythonモジュール内でRelatedを定義する典型例です:
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
partner_country_id = fields.Many2one(
related='partner_id.country_id',
string='Customer Country',
store=True,
)
この例ではpartner_idからres.partnerを辿り、そのcountry_idを読み取って受注レコード上にMany2oneとして表示しています。元の顧客データを参照しているだけで、値の重複は発生しません。
保存(Stored)と非保存(Unstored)の違い
ここが最も重要なポイントです。Relatedはデフォルトでstore=Falseになっており、レコード読み取り時にその場で計算されます。モデルのテーブルに列として保存されるわけではありません。
store=Trueにすると、参照元が変更された際にOdooが値をDB列へ書き込みます。これによりリストのフィルタ、グルーピング、検索が可能になり、レポートや集計で役立ちます。
ただし保存する分だけストレージを消費し、参照元の変更に対する更新トリガーが増えます。依存関係の追跡はOdooが自動で行いますが、レコード数が多く頻繁に更新が発生するモデルでは性能面の影響を考慮する必要があります。
読み取り専用と書き込み可能の違い
標準ではRelatedは読み取り専用です。readonly=Falseにすると編集可能になりますが、ユーザーが値を書き換えるとその変更はチェーンを通じて参照元のレコードに書き戻されます。つまり受注上で編集した値が実は顧客レコードを直接更新してしまう、といった挙動になります。
この書き戻しは強力ですが誤用は危険です。リストビューでのクイック編集など有用な場面はありますが、共有データを意図せず変更させないために、用途を明確にしてから有効にしてください。
主要なフィールド属性
Relatedフィールドで設定する代表的なパラメータは次のとおりです:
- related:ドット区切りのフィールドチェーン(例 'partner_id.country_id')。これが必須属性です。
- store:TrueにするとDBに永続化され、フィルタや集計が可能になります。
- readonly:Falseにするとユーザーが編集でき、変更は参照元へ伝播します。
- string:画面に表示するラベル。指定しないと末端フィールドのラベルが使われます。
- depends:通常は不要。Odooはrelatedチェーンから依存関係を自動推定します。特殊なケースでのみ明示します。
Odoo ORMとの相互作用
Relatedフィールドを読み取ると、チェーン末端の値を返します。途中のリンクが空(例えばpartner_idが未設定)ならFalseを返すのが標準挙動です。これはOdooのリレーション全般に共通するルールです。
Storedにしていればドメインやレポートで自由に使えます。非保存のRelatedはフォームやリストで表示できますが、検索ドメインでDBレベルのフィルタに使うことはできません(サーバー側でPython評価される場合を除く)。
業務での活用例
Relatedフィールドは実務のあらゆる場面で活用できます。ここでは代表的な5つのユースケースを紹介します。
営業・CRM:受注上での顧客電話番号表示
営業担当からよくある要望は「受注画面で顧客の電話番号をすぐ見たい」というものです。sale.orderにrelated='partner_id.phone'を追加すれば、顧客レコードを開かずに電話番号が見られるようになります。現場対応が速くなり、Odoo Studioなら1分以内に追加可能です。
会計:請求行上での会社通貨表示
複数会社を扱う環境では、請求書行で会社通貨を表示したいことがあります。move_id.company_id.currency_id のように二段階で辿るRelatedを作れば可視化できます。ただしチェーンが長くなると保守性や性能に影響するため注意が必要です。store=Trueにすれば通貨での絞り込みや分析も可能になります。
在庫:移動明細における製品カテゴリ表示
倉庫作業者が商品ごとのカテゴリを確認したいとき、stock.move.lineにproduct_id.categ_idをRelatedで出すと便利です。store=Trueにすれば入出庫をカテゴリで集計でき、商品群が多い企業での在庫報告に役立ちます。
製造:作業指示の部品に内部品番を表示
製造現場では作業指示中に部品の内部品番をすぐ見たい場面が多いです。mrp.workorderの部品行にproduct_id.default_codeをRelatedで表示すれば、類似部品の誤選択を減らし現場品質が向上します。
勤怠・プロジェクト:タイムシート上の従業員所属部署表示
プロジェクト管理でコスト配分をする際、タイムシート行に従業員の部署を見たいことがあります。account.analytic.lineにemployee_id.department_idをRelatedで追加し、store=Trueにすれば部署での絞り込みができ、プロジェクト分析に活用できます。
Relatedフィールドの作成・カスタマイズ方法
Relatedフィールドを追加する方法は主に3つあります。環境や運用ポリシーに応じて選んでください。
Odoo Studio(ノーコード)を使う方法
Odoo StudioならPythonを書かずにRelatedフィールドを作成できます。手順は簡単です:
- メインメニューからOdoo Studioを開く。
- フィールドを追加したいフォームへ移動する。
- 「フィールドを追加」をクリックし、「Related Field」を選ぶ。
- 表示されるフィールドを順にクリックしてリレーションパスを指定する。
- ラベルと保存/読み取り専用の設定を行う。
- Studioを保存して閉じる。
Studioは自動的にx_studio_接頭辞のフィールドを作成してビューに配置します。データベース定義の手作業は不要で、既存フォームに文脈情報を素早く追加するのに最も手軽な方法です。
Pythonでカスタムモジュールを書く方法
開発者はモデル定義内でRelatedフィールドを宣言します。バージョン管理やステージング環境への展開が必要な変更はこの方法が推奨されます。
from odoo import fields, models
class StockMoveLine(models.Model):
_inherit = 'stock.move.line'
product_category_id = fields.Many2one(
related='product_id.categ_id',
string='Product Category',
store=True,
)
定義後は該当ビューのXMLにフィールドを追加して表示させます。モジュールのインストールやアップグレード時にOdooが自動でDBカラムを作成するため、堅牢で保守しやすい方法です。
XML-RPC APIを使う方法
リモートで構成を自動化する場合は、XML-RPC API経由でir.model.fieldsにrelated属性を設定してフィールドを作成できます。
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_partner_country_id',
'field_description': 'Customer Country',
'model_id': sale_order_model_id,
'ttype': 'many2one',
'relation': 'res.country',
'related': 'partner_id.country_id',
'store': True,
'readonly': True,
'state': 'manual',
}]
)
API経由ではチェーンから型やリレーションを自動推定しないため、ttypeやrelationを正しく指定する必要があります。自動化スクリプトでのフィールド展開に向いた手法です。
推奨される運用ルール
運用上のベストプラクティス
1) フィルタやグループで使うなら必ずstore=Trueにする: 非保存のままだとDBレベルでの絞り込みが不可能で、大量データではスケールしません。表示だけなら非保存で問題ありません。
2) チェーンは短く保つ: partner_id.country_idのような二段階が理想です。picking_id.sale_id.partner_id.country_idのような深いチェーンは故障ポイントが増え、保守も難しくなります。深くなる場合は明示的な計算フィールドを検討してください。
3) readonly=Falseの意味を正確に理解する: 書き込み可能にすると参照元を書き換えることを意味します。他のドキュメントに影響が及ぶため、業務側と合意してから有効化してください。
4) 表示用途に留め、データ複製には使わない: 元データと切り離した独立した値を持ちたいなら、通常のフィールドにonchangeや自動アクションで初期値をセットする方法の方が適切です。
5) アクセス権を確認する: Relatedは別モデルを読み取るため、現在のユーザーにチェーン中のモデルへの読取権限がないと空値になります。表示設計時に期待するロールが該当モデルを参照できるか確認してください。
よくある間違いと対処法
非保存Relatedでのフィルタ化を期待する誤り
最も多いミスの一つは、リストビューにRelatedを追加してから検索フィルタを設定しようとして失敗するケースです。store=FalseのままではDBでの検索ができません。検索やグループ化に使う予定がある項目は必ずstore=Trueにしてください。
意図せぬ書き戻し(write-through)
よくある落とし穴
Studioで簡単にRelatedを追加してreadonlyを外してしまい、変更が参照元に波及してしまう事例もよく見られます。編集させる前にステークホルダーと“これを編集すると元レコードが変わる”ことを共有してください。
中間フィールドが空の場合の未処理
チェーン内のどれかが未設定だとRelatedはFalseを返します。フォーム上では空表示になり、Pythonで読み取る場合はFalseチェックを入れないとTypeErrorが発生することがあります。本番データでは必ず発生し得るのでテストで見落とさないようにしましょう。
Relatedで対処すべきでないロジックを無理に入れること
単純に別モデルの値を鏡像する用途には向いていますが、値に加工や条件分岐が必要な場合は計算フィールド(Computed field)を使うべきです。Relatedで無理に条件ロジックを実装すると将来のメンテナンス性やアップグレード互換性で問題になります。
大量モデルで多くの保存済みRelatedを使ったときの性能負荷
保存されたRelatedは参照元が更新されるたびに更新処理が走ります。数十万レコードを持つモデルに多数のStored Relatedを追加するとDBへの書き込み負荷が増大します。大規模環境ではパフォーマンスを計測し、リアルタイム性が不要なものは非保存で表示のみとする方針が有効です。
Relatedフィールドは、データを複製せずに文脈情報を表示するうえで非常に実用的なツールです。リレーションをたどって別モデルの値をそのままビューに出せるので、フォームやリスト、レポートでの可視性を高められます。
store=Trueを使うべきケース、readonly=Falseを許容するかの判断、チェーン中の空値の扱い方を知ることで、導入後のトラブルを大幅に減らせます。開発者、Studioを使うコンサルタント、リモート設定を管理する担当者いずれにとってもRelatedは役立つ知識です。
Odooのデータモデルを設計・拡張する際、RelatedはComputedやMany2oneなど他のフィールド型と並んで覚えておくべき重要なツールの一つです。適切に使えばコードを書かずに実務的な改善がすぐ行えます。
まとめ
Dasoloでは、セールス、オペレーション、会計などの領域でOdooの導入・カスタマイズ・最適化を支援しています。データモデル設計やフィールド追加、堅牢なコードによる拡張が必要であればご相談ください。
お気軽にご連絡いただければ、貴社のOdooプロジェクトをどのように支援できるかを一緒に検討します。
お問い合わせはこちら
ご相談の上、貴社に最適なOdoo設計・実装の提案を差し上げます。 ご連絡をお待ちしています。 お話を伺い、貴社のOdoo導入を前に進めるお手伝いをさせてください。