MY HATCH

Odoo の技術スタック解説 — Python+OWL+PostgreSQL

Odoo 19 Community が何で動いているかを、実際のコンテナの中で版を確かめながら説明します。画面の OWL、Python のサーバー、PostgreSQL、通知と裏の処理の仕組みまで。

6分
最終更新: 2026年10月26日
Odoo Community技術スタック開発
目次

目次

このページには目次がありません

Odoo の技術スタック解説 — Python+OWL+PostgreSQL

Odoo は、Python のサーバー、OWL という JavaScript の画面の仕組み、PostgreSQL のデータベースの 3 つで動いています。足りない機能をアドオンで足すときも、どこに何を書くかはこの 3 つの分担で決まります。

この記事の版や数は、当社の検証用の Odoo(公式のイメージ odoo:19.0・Odoo Server 19.0-20261015)のコンテナの中で、コマンドを叩いて確かめた物です。

全体の形

Odoo 19 の構成:ブラウザの OWL、Python の Odoo サーバー、PostgreSQL

層中身確かめた版
画面OWL(JavaScript の部品+XML のテンプレート)OWL 2.8.4
サーバーOdoo(Python)。HTTP は Werkzeug、PDF は wkhtmltopdfOdoo Server 19.0-20261015・Python 3.12.3
データベースPostgreSQL(psycopg2 で接続)PostgreSQL 16.15

Odoo 19 は Python 3.10 以上、PostgreSQL 13 以上を求めます(起動時に版を確かめる処理が入っています)。データベースは PostgreSQL だけで、ほかのデータベースは選べません。

サーバー:Python の Odoo

サーバーは 1 つの Python のプログラムで、次の物をまとめて持っています。

  • HTTP の受け口:画面からの呼び出しは /web/dataset/call_kw(JSON-RPC)、外のシステムからは /json/2/<モデル>/<メソッド> で受けます
  • ORM:受注・請求・品目などのモデルを Python のクラスで書き、表の作成や列の追加は Odoo が行います。見本の会社(販売・購買・在庫・会計・製造・経費を入れた状態)では、テーブルが 641 ありました
  • アドオン:公式の配布物には 692 個のモジュールが入っていて、販売も在庫も同じ形のアドオンです

主な Python のライブラリは、psycopg2 2.9.9(PostgreSQL への接続)、Werkzeug 3.0.1(HTTP)、lxml 5.2.1(画面の XML)、reportlab 4.1.0、gevent 24.2.1(通知の待ち受け)でした。帳票の PDF は、HTML で組んだ帳票を wkhtmltopdf 0.12.6.1 で PDF にしています。

アドオンの書き方は「本格拡張はアドオンで — Odoo の拡張開発の基本」で説明しています。

画面:OWL

Odoo の画面は、Odoo 社が作った OWL という仕組みで組まれています。部品を JavaScript のクラスで書き、見た目を XML のテンプレートで書く形です。web アドオンの画面のソース(static/src)では、526 本の JS ファイルのうち 228 本が @odoo/owl から部品を読み込んでいました。

たとえばチェックボックスの部品は、次のように書かれています(公式のソースから抜粋)。

import { Component } from "@odoo/owl";

export class CheckBox extends Component {
    static template = "web.CheckBox";
    static props = {
        value: { type: Boolean, optional: true },
        disabled: { type: Boolean, optional: true },
        onChange: { type: Function, optional: true },
    };
}
<t t-name="web.CheckBox">
    <div class="o-checkbox form-check" t-on-click="onClick">
        <input type="checkbox" class="form-check-input"
               t-att-checked="props.value" t-att-disabled="props.disabled"/>
        <label class="form-check-label"><t t-slot="default"/></label>
    </div>
</t>

アドオンで画面を変えるときも、この XML のテンプレートを継承して足します。公式のファイルは書き換えません。

ポイント!

当社は、日本の業務向けの画面を Vue3+TypeScript で作り、Odoo の中に載せる形も試しています。Odoo のメニューから開くと、その画面だけ Vue の部品を読み込んで表示し、閉じると片付けます。データは Odoo のサーバーに JSON-RPC で聞くので、権限や数字は Odoo の画面と同じです。OWL の画面と Vue の画面は、同じメニューの中に並べられます。

通知:PostgreSQL の LISTEN / NOTIFY

ほかの人が更新した内容やチャットのメッセージは、画面を読み直さなくても届きます。Odoo では、この通知を PostgreSQL の LISTEN / NOTIFY で受け渡しています。

  1. サーバーの処理が、通知を bus アドオンの表に書き、NOTIFY imbus を送る
  2. 通知の待ち受け役が LISTEN imbus で受け取る
  3. 開いている画面へ /websocket で届ける

通知のためにキューのサーバーや Node.js のサーバーを別に立てる必要はなく、PostgreSQL と Odoo のサーバーだけで完結します。

裏の処理:ir.cron

メールの取り込みや、たまった送信待ちのメールを送るような時間のかかる処理は、定期処理(ir.cron)として裏で動かします。見本の会社のデータベースには、公式のアドオンが入れた定期処理が 32 件あり、うち 25 件が有効でした。定期処理を動かすスレッドは、既定で 2 つです。

アドオンで足すときは、定期処理の行を XML で配り、処理そのものはモデルのメソッドに書きます。すぐに動かしたいときは、その定期処理を _trigger() で呼び起こします。

1 台から、分けて増やすまで

設定の workers が 0 のとき(今回の検証用もこの形)、Odoo は 1 つのプロセスの中で、HTTP・通知・定期処理をスレッドで動かします。小さく始めるなら、Odoo のサーバー 1 台と PostgreSQL で足ります。

workers を 1 以上にすると、形が変わります。

役受け持つ物
HTTP のワーカー画面と外のシステムからの呼び出し(workers の数だけ立つ)
定期処理のワーカーir.cron の処理
通知のプロセスgevent で websocket を待ち受ける(既定のポート 8072)

人が増えたら HTTP のワーカーを、裏の処理が重くなったら定期処理のワーカーを増やします。前にリバースプロキシを置き、/websocket だけ通知のプロセスへ振り分けます。データベースは PostgreSQL なので、バックアップやレプリカは PostgreSQL の道具をそのまま使えます。

まとめ

  • Odoo は Python のサーバー、OWL の画面、PostgreSQL の 3 つで動く
  • 通知は PostgreSQL の LISTEN / NOTIFY、裏の処理は ir.cron。別のサーバーを足さずに始められる
  • 増やすときは workers で、HTTP・定期処理・通知を別のプロセスに分ける
  • 足すときは、どの層もアドオンで継承して足す。公式のソースは書き換えない

版を上げても足した物が動き続ける作り方は「アップデートしても壊れない — Odoo の拡張の作り方」にまとめています。

「作り方」の記事をもっと見る

ERP を、借りずに所有する。

Odoo Community を日本の業務に合わせ、ソース一式を人数無制限でお渡しします。

相談する(無料)