Odoo 14 OWLにおけるモデルメソッドの呼び出しとres_idの取得方法

Odoo 14から導入されたOWL(Odoo Web Library)は、フロントエンド開発を大幅に強化しましたが、初期段階のフレームワークであるため、公式ドキュメントだけでは実装方法が不明確な場合があります。特にカスタムウィジェットを作成する際、現在のレコードID(res_id)の取得や、サーバーサイドのモデルメソッドの実行(RPC呼び出し)は頻繁に必要となる操作です。

レコード情報へのアクセス

OWLのコンポーネント、特にフィールドを拡張する AbstractFieldOwl を継承したクラス内では、this.record プロパティを介してレコードのデータにアクセスできます。現在のレコードIDを取得するには以下のプロパティを参照します。

// 現在のレコードのIDを取得
const currentId = this.record.res_id;

モデルメソッドの実行(RPC呼び出し)

Python側のモデルで定義したメソッドを呼び出すには、this.rpc を使用します。これにより、バックエンドのロジックを実行し、その結果を非同期で取得してUIに反映させることが可能です。

以下に、AbstractFieldOwl を使用してカスタムフィールドを定義し、サブコンポーネントと通信しながらデータを取得する実装例を示します。

JavaScript 実装例

odoo.define('custom_module.team_viewer', function (require) {
    "use strict";

    const { Component } = owl;
    const AbstractFieldOwl = require('web.AbstractFieldOwl');
    const fieldRegistry = require('web.field_registry_owl');

    // 子コンポーネント:個別メンバーのカード表示
    class TeamMemberCard extends Component {
        static template = 'TeamMemberCardTemplate';
        
        onCardClick() {
            // 親コンポーネントにイベントを通知
            this.trigger('member-selected', {
                memberId: this.props.memberId
            });
        }
    }

    // メインコンポーネント:フィールドウィジェット
    class TeamDisplayWidget extends AbstractFieldOwl {
        static supportedFieldTypes = ['many2many'];
        static template = 'TeamDisplayMain';
        static components = { TeamMemberCard };

        constructor(...args) {
            super(...args);
            this.membersData = [];
        }

        async willStart() {
            const contextId = this.record.res_id;
            if (contextId) {
                // モデルメソッドの呼び出し
                this.membersData = await this.rpc({
                    model: 'res.partner',
                    method: 'search_read',
                    domain: [['id', 'in', this.value.res_ids]],
                    fields: ['id', 'name', 'email'],
                });
            }
        }

        async onMemberDetailRequest(ev) {
            const partnerId = ev.detail.memberId;
            // バックエンドのアクション定義を取得する例
            const action = await this.rpc({
                model: 'res.users',
                method: 'get_external_user_action',
                args: [partnerId],
            });
            
            // 注意: OWLコンポーネント内では従来の this.do_action は直接利用できないため、
            // AbstractFieldOwl のコンテキストに応じたアクション制御が必要です。
            console.log("Action data retrieved:", action);
        }
    }

    fieldRegistry.add('team_member_viewer', TeamDisplayWidget);

    return TeamDisplayWidget;
});

XML テンプレート実装例

OWLのテンプレートでは owl="1" 属性を付与し、t-on- ディレクティブを使用してイベントハンドリングを行います。

<templates>
    <!-- 子コンポーネントのテンプレート -->
    <t t-name="TeamMemberCardTemplate" owl="1">
        <div class="card p-2 m-1 shadow-sm" t-on-click="onCardClick" style="cursor: pointer;">
            <div class="card-body">
                <h6 class="card-title">
                    <t t-esc="props.name"/>
                </h6>
                <p class="small text-muted">ID: <t t-esc="props.memberId"/></p>
            </div>
        </div>
    </t>

    <!-- メインウィジェットのテンプレート -->
    <div t-name="TeamDisplayMain" owl="1" t-on-member-selected="onMemberDetailRequest">
        <div class="d-flex flex-wrap">
            <t t-foreach="membersData" t-as="m" t-key="m.id">
                <TeamMemberCard name="m.name" memberId="m.id"/>
            </t>
        </div>
    </div>
</templates>

実装のポイント

Odoo 14のOWL環境において、ビューの遷移(do_action)を伴う高度な操作を行いたい場合は、web.AbstractFieldOwl を利用してレガシーなWebクライアント層との互換性を保つのが一般的です。純粋なOWLコンポーネント内では、env を通じてサービスにアクセスし、アクションマネージャーを呼び出す設計が求められます。res_id を起点にRPCでデータを動的に取得することで、標準機能では難しい柔軟なUI表現が可能になります。

タグ: Odoo14 OWL javascript RPC OdooFramework

5月19日 21:44 投稿