はじめに
Odooの各フォームには多くの入力欄があり、毎回手で埋める必要がある項目もあります。しかし多くのフィールドは「最初から使える値」を設定しておけるため、ユーザーがフォームを開いた瞬間から実用的な状態にできます。デフォルト値の仕組み自体は単純ですが、設定やカスタマイズの現場では複数のレイヤーが絡むため、設計段階で正しく理解しておくことが重要です。
Odoo Studioでビジネスユーザーが簡単に設定する場合もあれば、開発者がPythonで細かく制御する場合もあります。どちらの立場でもデフォルトの仕組みを押さえておけば、作業時間を短縮できるだけでなく、後で気づきにくい設定ミスを未然に防げます。
本ガイドでは、Odooにおけるデフォルト値の基本概念、ORMレベルでの動作、静的デフォルトと動的デフォルトの使い分け、そしてOdoo StudioやPythonでの設定方法までを実務向けに解説します。
Odooにおけるデフォルト値とは何か
OdooのORMにおいてデフォルト値とは、新しいレコード作成時にユーザーが入力する前にフィールドに割り当てられる初期値のことです。制約ではなくあくまで出発点なので、ユーザーは自由に値を変更できます。のちのデータ入力を楽にするための“初期設定”だと考えてください。
defaultパラメータはChar、Integer、Float、Boolean、Date、Many2one、Selectionなどほぼ全てのフィールドで利用可能です。単純な定数、Pythonのラムダ、メソッド参照などを使い分けられ、ユースケースに応じて適切な手段を選べます。
Odoo Studioではフィールドプロパティパネルにシンプルな「デフォルト値」入力があり、コードを書かずに静的な初期値を設定できます。開発者を呼ばずにデータ整合性を改善できるため、日常的な調整には非常に使いやすい方法です。
データベースレベルでは、デフォルト値が実際にカラムに格納されるわけではありません。デフォルトはPythonモデル定義内か、ir.defaultレコードとしてDBに保存されます。新規レコード作成時にOdooがこれらの設定を読み取ってフォームを事前入力します。
デフォルト値がどのように動作するか
ユーザーが新規フォームを開くと、フレームワークはモデル上のdefault_get()を呼び出します。これにより各フィールドの初期値が収集され、フィールド名と値の辞書として返され、フォームが事前入力されます。
Odooのデフォルトには主に4種類があり、それぞれ異なる用途に適しています。
静的デフォルト
フィールド定義やStudioで固定値を設定する方法です。たとえばBooleanをTrueにしたり、Selectionを'draft'にするようなシンプルな使い方は、日常の多くのケースで十分に機能します。
ラムダやメソッドによる動的デフォルト
レコード作成時に評価されるPython関数やラムダを使う方法です。現在の日付やログイン中ユーザー、コンテキスト情報に依存した初期値が必要なときに使います。たとえば担当者を現在のユーザーにする、日付を今日にする、といった設定です。
以下はPythonモデル内で静的・動的デフォルトを使う典型的な例です。
from odoo import fields, models
class CrmLead(models.Model):
_inherit = 'crm.lead'
# 静的デフォルト
x_priority_level = fields.Selection(
[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')],
string='Priority Level',
default='medium',
)
# 動的デフォルト: 現在のユーザー
x_assigned_by = fields.Many2one(
'res.users',
string='Assigned By',
default=lambda self: self.env.user,
)
# 動的デフォルト: 今日の日付
x_expected_date = fields.Date(
string='Expected Close Date',
default=lambda self: fields.Date.today(),
)
コンテキストベースのデフォルト
アクションのコンテキストでdefault_field_nameというキーを渡すことで設定される初期値です。関連レコード内から「作成」したときに親レコードの情報を自動的に渡す、という使われ方が多く、プロジェクト内からタスクを作るとプロジェクト欄が自動入力されるのはこれに当たります。開発者や上級ユーザーがカスタムアクションで渡すことも可能です。
ユーザー別デフォルト(ir.default)
ir.defaultを使うとユーザーごとの個別初期値を設定できます。管理者が特定ユーザーのためにフィールドの既定値を登録すると、そのユーザーが新規レコードを作成した際に個人設定が優先されます。チームごとに作業スタイルが違う環境で便利な機能です。
優先順位
同じフィールドに複数のデフォルトがある場合、Odooは次の順で解決します:ユーザー固有のir.default→会社レベルのir.default→Pythonモデル定義のデフォルト。さらに、ランタイムで渡されたコンテキストベースのデフォルトはモデルレベルの値を上書きします。期待した値が表示されないときはこの順序を確認すると原因が見つかることが多いです。
業務での利用シーン
デフォルトはほぼ全てのモジュールで役立ちます。以下は実務でよく見かける具体例です。
CRM:新規リードの担当者デフォルト
営業が新しいリードを作成すると担当者欄を現在のユーザーにすることで、未割当のリードを減らせます。モデル内でlambda self: self.env.userを使うだけの小さな工夫ですが、ユーザーが自分の案件をすぐに確認できるためCRMの利用定着率が上がります。
販売:受注の支払条件デフォルト
顧客に紐づいた価格表や支払条件を受注作成時に自動で設定することで、担当者ごとの設定漏れや手入力ミスを防げます。たとえば取引先に対してNet30が設定されていれば、新しい受注にその条件があらかじめ入ります。
在庫:振替のデフォルトロケーション
倉庫設定に基づいて出庫元・入庫先ロケーションをあらかじめ選んでおけるため、同じゾーンで作業するスタッフはフォームを開いた瞬間に正しいロケーションが選択されています。作業効率が上がり、誤選択によるミスも減ります。
会計:仕訳のデフォルトジャーナル
新しい請求書や仕訳を作る際に、仕訳種別や会社設定に基づく適切なジャーナルを初期設定することで、経理担当者が毎回ジャーナルを選ぶ手間を省けます。会社側の設定に従って動的に解決されるため、後でジャーナル構成が変わっても整合性が保たれます。
プロジェクト:タスクの初期ステージ
プロジェクト内でタスクを作ると、そのプロジェクトのカンバンで最初のステージに自動配置されます。さらにプロジェクト画面から作成した場合はコンテキストでプロジェクトや担当者が埋まることもあり、チームはタスクが適切な位置からスタートするため管理がしやすくなります。
デフォルト値の作成・カスタマイズ方法
デフォルトを設定する方法は主に3つあります。Studioでコード不要に行う方法から、モジュールでPythonを使う方法まで用途に応じて使い分けます。
Odoo Studioを使う(ノーコード)
Odoo Studioはフォーム上の任意フィールドに対して視覚的にデフォルト値を設定できるインターフェースを提供します。設定手順は次の通りです。
- 変更したいフォームでStudioを開く
- 設定したいフィールドをクリックする
- 右側のフィールドプロパティで「デフォルト値」欄を探す
- 開始時に入れたい値を入力または選択する
- 保存してStudioを終了する
Studioはこの設定をDB内のir.defaultレコードとして保存します。ユーザー範囲の指定が無い限り会社全体で適用されます。Selection、Boolean、Char、Integerなどの静的デフォルトに向いており、Many2oneは既存レコードを選ぶドロップダウンが使えます。コードを書かずに素早く改善できるため非常に実用的です。
注意点として、Studioでデフォルトを変更しても既に作成済みのレコードには影響しません。新しいデフォルトは設定後に作られるレコードにのみ適用されます。
技術的カスタマイズでPythonを使う場合
開発者はフィールド定義内で直接defaultを設定できます。これにより静的値やラムダ、複雑なメソッドを使った動的デフォルトまで柔軟にコントロールできます。ランタイム情報(現在ユーザーや日付、会社設定など)に依存する場合はこちらが適切です。
カスタムモジュールに追加する代表例は次の通りです。
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
# 静的Booleanデフォルト
x_requires_review = fields.Boolean(
string='Requires Review',
default=False,
)
# 静的Selectionデフォルト
x_delivery_preference = fields.Selection(
[('standard', 'Standard'), ('express', 'Express')],
string='Delivery Preference',
default='standard',
)
# メソッドを使った動的デフォルト
def _default_note(self):
return self.env['ir.config_parameter'].sudo().get_param(
'sale.default_note', default=''
)
x_internal_note = fields.Text(
string='Internal Note',
default=_default_note,
)
このやり方はOdooのPythonフィールド定義の慣習に沿っており、どのフィールドタイプでも使えます。特にメソッドベースのデフォルトは、ラムダでは表現しにくい複雑なロジックに有効です。
ir.defaultレコードをプログラムで操作する
ir.defaultはXML-RPCやモジュールのデータファイルから作成・更新できます。カスタムモジュールのインストール時に初期構成としてデフォルトを配布したい場合に便利です。モデル名、フィールド名、値、必要に応じて会社やユーザーを指定してスコープを決められます。
日常的な開発ではあまり頻繁に使いませんが、配布可能なモジュールに初期設定を同梱する際には役立つ手法です。
Odooでのデフォルト値に関するベストプラクティス
必須フィールドにはデフォルトを設定する
必須フィールドには妥当な初期値を設定しておくことで、ユーザーが気づかずにエラーで保存できない事態を減らせます。必須+実用的なデフォルトの組み合わせはデータモデル全体で推奨されるパターンです。
日付デフォルトはラムダで設定する
日付をハードコーディングしてはいけません。lambda self: fields.Date.today()のようにしておけば、レコード作成時点の現在日付が自動的に入ります。固定日付をベタ書きすると、その時点を過ぎた瞬間から誤った値になるため実用性がありません。
デフォルトロジックは軽量に保つ
デフォルト関数はフォームを開くたびに実行されます。重いDBクエリや外部APIコール、計算負荷の高い処理を入れるとユーザーのUXが悪化します。複雑な処理が必要ならonchangeや別の計算フィールドに分離することを検討してください。
ナビゲーションで使うデフォルトはコンテキストで渡す
カスタムアクションやスマートボタンで新規フォームを開く場合は、モデルの静的デフォルトに頼るよりアクションのコンテキストでdefault_field_nameを渡すほうが自然です。これはOdooのネイティブな動作に合致する設計です。
複数ユーザープロファイルでデフォルトをテストする
self.env.userやself.env.companyを参照する動的デフォルトは、ログインユーザーや会社によって挙動が変わります。管理者だけでなく一般ユーザーや別会社のアカウントでも必ず動作確認を行ってください。管理者環境で動いても本番ユーザーだと想定と異なる結果になることがあります。
よくある落とし穴
可変オブジェクトをデフォルトにしない
Pythonの典型的な落とし穴ですが、default=[]やdefault={}のように可変オブジェクトを直接指定すると、インスタンス間で同じオブジェクトが共有されてしまいます。必ずラムダを使って新しいオブジェクトを返すようにしてください:default=lambda self: []。
デフォルトはonchangeをトリガーしない
デフォルト値が設定されてもonchangeは発火しません。フォーム上でonchangeにより他フィールドが更新される設計の場合、デフォルトだけだとその更新が行われません。初期化時にonchangeの副作用が必要なら、default_getをオーバーライドして明示的に呼ぶか、別の手法で処理を実装してください。
ir.defaultとモデル定義での競合
Pythonで定義したデフォルトとStudioやir.defaultでの設定が競合する場合、Odooは優先順位に従ってir.default側を優先します。Studioでの変更が意図せずコード側の設定を上書きしてしまい混乱することがあるため、デバッグ時はこの点をまず確認してください。
デフォルトがあるからといって必須とは限らない
デフォルトが設定されているだけではフィールドが必須になるわけではありません。ユーザーが値をクリアすれば空のまま保存されます。本当に必ず値が必要ならrequired=Trueとデフォルトを組み合わせてください。
会社やユーザーのレコードIDをハードコードしない
default=1のようにIDを直接指定するのは脆弱です。環境ごとにIDは異なるため、本番環境で壊れる原因になります。常に動的参照を使う:lambda self: self.env.company.idやlambda self: self.env.ref('module.xml_id').idのようにしてください。
まとめ
デフォルト値は小さな機能ですが効果は大きく、手入力の手間を減らし、ユーザーに一貫した選択肢を示し、フォームの使いやすさを向上させます。Odoo Studioで手早く設定する方法でも、Pythonで丁寧に制御する方法でも、仕組みを正しく理解しておくことが良い実装につながります。
押さえておくべき要点は次の通りです:デフォルトはレコード作成時にのみ評価されること、onchangeは起動しないこと、複数のデフォルトは優先順位に従って解決されること、そしてリストや辞書などの可変オブジェクトはラムダで生成すること。
デフォルトを適切に設計するかどうかで、フォームが直感的に使えるか、それとも毎回ユーザーにストレスを与えるかが決まります。少しの手間で日々の作業がずっとスムーズになるため、投資する価値は高いです。
Dasoloでは、企業の業務フローに合わせたOdooの導入、カスタマイズ、最適化を支援しています。フィールドのデフォルト設定、カスタムフィールドの構築、現場に合うデータモデル設計などでお困りでしたらぜひご相談ください。 お問い合わせはこちら お客様のOdoo導入について一緒にお話ししましょう。