odoo-orm-expert について
Odoo ORM を扱う開発者向けのガイドスキルです。データ操作、ドメインフィルター、計算フィールドの実装やクエリ性能の調査に使えます。慣用的なコード例を示し、バッチ処理、アクセス制御、ループ内検索などの注意点を扱います。
主な機能
- 01レコード CRUD 操作の案内
- 02ドメインフィルターの作成
- 03計算フィールドと関連フィールドの実装
- 04ORM の性能パターンの確認
- 05N+1 クエリの回避
- 06アクセス権とレコード範囲の考慮
活用シーン
- 01Odoo の検索・書き込み処理の作成
- 02ビューやサーバーアクション用のレコード絞り込み
- 03レコードの一括更新の最適化
- 04遅い ORM クエリの調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill odoo-orm-expertインストール後、Claude Code で/odoo-orm-expertを入力して読み込まれたか確認します。
詳細
Odoo ORM エキスパート
概要
このスキルでは、Odoo のオブジェクトリレーショナルマッパー(ORM)について詳しく説明します。レコードの読み取り/書き込み、ドメインフィルターの作成、リレーショナルフィールドの操作、N+1 クエリなどの一般的なパフォーマンス上の問題の回避方法を扱います。
このスキルを使用する場面
search()、browse()、create()、write()、unlink()の呼び出しを記述するとき。- ビューまたはサーバーアクション用の複雑なドメインフィルターを作成するとき。
- 計算フィールド、格納フィールド、関連フィールドを実装するとき。
- クエリの遅延をデバッグしたり、一括操作を最適化したりするとき。
動作の仕組み
- 有効化:
@odoo-orm-expertに言及し、必要なデータ操作を説明します。 - コードの取得:説明付きで、正しく慣用的な Odoo ORM コードを受け取ります。
- 最適化:既存の ORM コードのパフォーマンスレビューを依頼します。
例
例 1:ドメインフィルターを使った検索
# Find up to 50 confirmed sale orders for a specific customer dated this UTC year
import datetime
year = datetime.datetime.now(datetime.timezone.utc).year
start_of_year = datetime.datetime(year, 1, 1) # Odoo stores naive UTC datetimes
start_of_next_year = datetime.datetime(year + 1, 1, 1)
orders = self.env['sale.order'].search([
('partner_id', '=', partner_id),
('state', '=', 'sale'),
('date_order', '>=', start_of_year),
('date_order', '<', start_of_next_year),
], order='date_order desc', limit=50)
# date_order is a Datetime field. For precise business-year boundaries,
# construct UTC datetime bounds from the intended business timezone;
# this example uses the UTC calendar year.
例 2:計算フィールド
total_order_count = fields.Integer(
string='Total Orders',
compute='_compute_total_order_count',
store=True
)
@api.depends('sale_order_ids')
def _compute_total_order_count(self):
for record in self:
record.total_order_count = len(record.sale_order_ids)
例 3:安全な一括書き込み(N+1 を回避)
# Batch writes reduce repeated calls, but can trigger additional compute/tracking queries
partners = self.env['res.partner'].browse(approved_partner_ids).exists() # Explicit scoped IDs
partners.write({'country_id': self.env.ref('base.us').id})
# ❌ BAD: Triggers a separate query per record
for partner in partners:
partner.country_id = self.env.ref('base.us').id
ベストプラクティス
- ✅ 推奨:Python のループではなく、レコードセットに対して
mapped()、filtered()、sorted()を使用します。 - ✅ 推奨:
sudo()は、セキュリティ上の影響を理解したうえで、必要最小限にのみ使用します。 - ✅ 推奨:件数だけが必要な場合は、
len(search(...))ではなくsearch_count()を使用します。 - ✅ 推奨:
self.env.contextを直接変更するのではなく、with_context(...)を使ってコンテキスト値を適切に渡します。 - ❌ 非推奨:ループ内で
search()を呼び出さないでください。これは Odoo のパフォーマンスを最も損なう原因です。 - ❌ 非推奨:どうしても必要な場合を除き、生の SQL を使用しないでください。標準的な操作にはすべて ORM を使用します。
- ✅ 推奨:値をフィールド型に合わせます。Date には日付またはサーバーの日付文字列を、Datetime には日時またはサーバーの日時文字列を使用します。Python の date/datetime オブジェクトもサポートされています。比較時に Datetime を Date に切り詰めたり、異なる型を混在させたりしないでください。Odoo の ORM における日付/時刻のガイダンスを参照してください。
制限事項
cr.execute()による生の SQL のパターンは詳しく扱いません。SQL レベルでの最適化には、Odoo パフォーマンスチューナーのスキルを使用してください。- 格納された計算フィールドは、大規模な環境では書き込みのオーバーヘッドを大幅に増やす可能性があります。このスキルではパーティショニング戦略を扱いません。
- 一時モデル(
models.TransientModel)やウィザードのパターンは扱いません。 - 設定のオーバーライドにより、Odoo SaaS とオンプレミスでは ORM の動作がわずかに異なる場合があります。
例は、インポート、レコード定義、認可されたスコープを必要とするモデルメソッドの断片です。国のデータが欠けていることから米国だと推測してはいけません。選択したレコードには、確認済みの値のみを書き込んでください。バッチ操作で SQL クエリが 1 つだけになるとは限りません。また、mapped/filtered によって大きなレコードセットが読み込まれる場合があります。実際のクエリ数をプロファイリングし、レコードルールとマルチカンパニーの分離をテストしてください。
コメント
Markdown 対応