はじめに
Odooのeコマース商品ページで、見出しが太字になり箇条書きや画像が組み合わさった商品の説明文──あの見たままのリッチな表示は、1つのフィールドタイプ、Htmlフィールドによって支えられています。Odooのデータモデルの中でも汎用性が高く、気づかないうちにあちこちで使われているフィールドです。
プレーンテキストがただの文字列を保持するのに対し、Htmlフィールドは装飾や構造を持つリッチコンテンツを格納します。商品説明やメールテンプレート、社内メモ、ウェブサイトのセクションなど、見た目やレイアウトが重要な箇所で必須となるフィールドです。
本稿では、Htmlフィールドの役割とOdooのORMやデータベース上での扱い方、業務での代表的な利用例、Odoo StudioやPythonモジュールでの作り方・変更方法、そしてこのフィールド特有の注意点とよくあるミスについて解説します。
OdooのHtmlフィールドとは何か
ORM上では、Htmlフィールドは整形されたHTML文字列を保存するために設計されています。PostgreSQLではTEXT型のカラムにマップされ、実際の値はHTMLとして格納されます。Odooはレンダリングとサニタイズ(無害化)を自動で行うため、ユーザーは生のHTMLを直接編集するのではなく、リッチテキストエディタとして操作できます。
ユーザーの目にはHtmlフィールドはWYSIWYG(見たまま編集)エディタとして映ります。太字や斜体、見出し、リスト、リンク、表、画像の挿入などが可能で、編集結果は裏側でHTMLとして保存されます。
Pythonのモデル定義では、フィールドをこう定義します(例示):
from odoo import fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
x_technical_specs = fields.Html(
string='Technical Specifications',
sanitize=True,
sanitize_tags=True,
)
The string parameter sets the visible label. The sanitize parameter controls whether Odoo strips potentially dangerous HTML before saving the value. This is important for security reasons and is enabled by default.
In Odoo Studio, this field type is called Html or Rich Text. When created through Studio, it gets an x_studio_ prefix. When defined in Python or via the XML-RPC API, you choose the technical name yourself.
フィールドの動作概要
Htmlフィールドを定義すると、フレームワークはPostgreSQLにTEXT型のカラムを作成します。データベース側に長さ制限がないため長文のコンテンツを扱えます。実際の値は記録される前にOdoo側でサニタイズされます。
サニタイズとセキュリティについて
Htmlフィールド最大の特徴はサニタイズ機能です。デフォルトでXSS(クロスサイトスクリプティング)に使われ得るタグや属性を除外する処理が入り、これはいくつかのフィールド属性で制御されます。
- sanitize: デフォルトでTrue。保存前に完全な無害化処理を行います。信頼できる内部プロセス以外からの入力に対しては無効化しないでください。
- sanitize_tags: Trueにすると、許可リスト外のHTMLタグは削除されます。これを無効にすると任意のタグを許可できますが慎重に扱う必要があります。
- sanitize_attributes: タグに付随する属性も無害化するかどうかを制御します。
- sanitize_style: インラインスタイル属性の扱いを制御します。危険なCSSは除去され、許可リストにあるプロパティだけ残されます。
- strip_style: Trueにするとインラインスタイル属性をすべて削除します。
- strip_classes: Trueにするとクラス属性がすべて除去されます。
このようなサニタイズ機構があるため、Htmlフィールドは外部ユーザーが入力するコンテンツでも比較的安全に使え、顧客向けフォームやメールテンプレートで多用されています。
主要なフィールド属性
サニタイズのほか、Htmlフィールドは一般的なOdooフィールド属性を備えています。
- translate: Trueにすると言語ごとにHTMLを翻訳・保存できます。多言語サイトでは必須の設定です。
- required: 必須にできます。ただし空タグや空白だけが入っている場合は見た目上は非空扱いになることがあるため、厳密なバリデーションが必要なケースでは注意が必要です。
- default: 新規レコードに初期HTMLを入れておく用途に便利です。メールテンプレートや定型文のプリセットに使えます。
- compute: Pythonメソッドで動的にHTMLを生成できます。
store=Trueをつければ計算結果をデータベースに保存します。 - copy: レコードをコピーしたときに内容を複製するかを制御します。デフォルトはTrueです。
ビューでの見え方
フォームビューではリッチテキストエディタとしてツールバーが表示され、画像やリンクを含む整形済みの文章を編集できます。リストビューでは可読性を保つためHTMLタグが除かれたプレーンテキストのプレビューが表示されることが多いです。
XMLビューのwidget属性で表示方法を調整できます。通常は編集可能なリッチエディタが使われますが、読み取り専用でそのままHTMLを出力するウィジェットに切り替えると、ポータルやレポートで編集ツールバー無しに整形済みコンテンツを見せられます。
ORMとのやり取り
開発者の観点では、Htmlフィールドを読むと生のHTML文字列が返り、書き込む際もHTML文字列を渡します。サニタイズはORMの段階で行われ、XML-RPC経由で値を書いてもsanitize=Trueなら同じクリーニング処理を通ります。
実務上の注意点として、カスタムタグや未許可属性を含めたい場合はsanitize=Falseにするか、サニタイズフラグを調整する必要があります。これは上級者向けで、運用環境のセキュリティリスクを十分に理解して行ってください。
ビジネスでの利用シーン
HtmlフィールドはOdoo内の多くの場所で使われています。ここでは業務でよく見かける5つの実例を紹介します。
在庫・EC:商品説明
Odooで最も広く使われているHtmlフィールドはproduct.templateのdescription_saleです。ECサイトに表示される商品説明をリッチに書けるため、マーチャンダイジング担当が見出しや箇条書き、画像を組み込み、購買率改善につなげられます。バックオフィスとフロントストアが同一レコードを参照するため、コンテンツの二重管理が不要なのも利点です。
メールマーケティング:テンプレート本文
mail.templateのbody_htmlはメール本文をまるごとHTMLで保存します。レイアウト、画像、差し込みプレースホルダを使って送信時に値が埋められるため、外部のデザインツールを使わずにOdoo内でリッチなメールを作成・再利用できます。キャンペーンや見積、ワークフローで使い回せるのも便利です。
CRM:ノートや商談説明
営業チームは案件や見込み客について詳細を残すことが多く、Htmlフィールドなら書式付きノートやリスト、外部資料へのリンクを保持できます。チームで共有したり印刷したりしても書式が保たれる点で、プレーンテキストより有用です。
会計:請求書の注意事項
請求書や受注の下部に支払条件や法的文言、保証情報を入れる際、sale.orderやinvoiceのnoteはHtmlフィールドになっています。PDF出力時に改行や強調が期待通り反映されるため、書式付きの条項を正しく見せられます。
人事:募集要項の説明文
採用モジュールで求人情報を掲載する際、hr.jobやhr.applicantの求人説明はHtmlフィールドに格納されます。職務内容・要件・待遇を見出しや箇条書きで整理して表示できるため、採用ページ上で読みやすく見映えの良い掲載が可能です。
Htmlフィールドの作成・カスタマイズ方法
Htmlフィールドをモデルに追加するには主に3つの方法があります。技術スタックや運用方針に応じて選んでください。
Odoo Studioを使う(ノーコード)
Odoo Studioならコーディング不要でフォームにHtmlフィールドを追加できます。手順は簡単です。
- メインメニューからOdoo Studioを立ち上げます。
- フィールドを追加したいフォームに移動します。
- サイドバーからHtmlまたはRich Textフィールドをドラッグしてフォーム上に配置します。
- フィールドのラベルやプロパティを設定します。
- 保存してStudioを閉じます。
Studio automatically creates the field with an x_studio_ prefix, adds it to the view, and handles the database column. No migration or deployment step is needed on your side. The field is immediately available for data entry across the instance.
カスタムモジュールでPythonを使う方法
モジュール開発者はPythonのモデルファイルでHtmlフィールドを定義します。バージョン管理やステージング→本番のデプロイが必要な変更はこちらがおすすめです。
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
x_delivery_instructions = fields.Html(
string='Delivery Instructions',
sanitize=True,
translate=True,
)
モデルに定義したら該当するXMLビューにフィールドを追加して見えるようにします。モジュールをインストールまたはアップグレードすればDBにTEXTカラムが自動で作成され、フォーム上ではリッチテキストエディタとして表示されます。
XML-RPC APIで作成する方法
運用の一環でリモートスクリプトやCIパイプラインからフィールドを作る場合、XML-RPC経由でもHtmlフィールドを作成できます。
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_custom_notes',
'field_description': 'Custom Notes',
'model_id': model_id,
'ttype': 'html',
'state': 'manual',
}]
)
ここでのttype: 'html'がHtmlフィールドを指示し、state: 'manual'はユーザー作成フィールドであることを示します。こうした自動化は複数環境への展開や設定の追跡に便利です。
ただし、API経由で作る場合はPython定義と同じようにサニタイズオプションを細かく設定できない点に注意してください。APIで作成したフィールドにはデフォルトのサニタイズ設定が適用されます。
運用上のベストプラクティス
1. 特別な理由がない限りsanitizeは有効のままにすること
サニタイズはXSS脆弱性からインスタンスを守るためにあります。ほとんどのケースでは有効のままで問題ありません。無効化するのは、サーバー側で生成され信頼できる処理からのみ供給されるコンテンツに限るべきです。ユーザー入力や外部ソース由来のデータには決して使わないでください。
2. 多言語コンテンツにはtranslate=Trueを設定する
多言語対応の環境で、ウェブ上や顧客向けドキュメントに表示されるHtmlフィールドは翻訳可能にしておきましょう。言語ごとにHTMLを管理することで、利用者が常に自分の言語で説明や条項を確認できるようになります。
3. 外部リソースに依存するHTMLは避ける
外部の画像やスクリプトを埋め込むと、参照先が変わったりダウンすると表示が崩れるリスクがあります。画像は可能な限りOdooの添付ファイルとして内部にホストし、相対パスや内部URLで参照することを推奨します。これによりDB移行やサーバ移行時の糸口が増えます。
4. 動的な文書は計算フィールドで作ると便利
注文行の要約や動的な保証文など、プログラムで組み立てる必要があるコンテンツはcompute付きのHtmlフィールド(store=True)で生成すると管理が楽になります。生成ロジックが一箇所にまとまり、表示やPDF出力でも性能面で有利です。
5. HtmlとTextの選択は表示コンテキストに応じて
バックエンドで単純に読むだけの用途ならTextフィールドで十分な場合があります。ウェブページや印刷物、メールの本文など、書式が重要な場面ではHtmlを選びましょう。不要にHtmlを使うとリッチエディタの操作が煩わしく、ユーザー体験を下げることがあります。
よくある落とし穴
サニタイズを無効にして放置してしまうこと
開発中に急いでsanitize=Falseにして要件を満たし、そのまま本番に出してしまうミスがよくあります。無効化した理由は必ず記録し、本番導入前に再評価・承認プロセスを設けてください。
外部から貼り付けたHTMLが壊れているケース
WordやGoogleドキュメント、他サイトからコピー&ペーストしたHTMLは冗長で不正なタグや不可視文字が混入しがちです。レンダリングが崩れたり検索でヒットしない、値が膨らんでページ表示が遅くなる原因にもなります。まずは「プレーンテキストで貼り付け」を推奨し、必要な装飾はOdooエディタ側でやり直す運用が望ましいです。
ウェブサイトビルダーのHTMLと混同すること
Odooのウェブサイトビルダーはブロックやコンポーネントでページを組み立てるため、生成されるHTMLはモデルのHtmlフィールドに入れるべきものとは構造が異なります。ウェブビルダー用の複雑なHTMLをそのままHtmlフィールドに貼ると、正しく表示されなかったりサニタイズで削られてしまうことが多いです。
多言語設定を忘れること
多言語環境でtranslate=TrueにしていないHtmlフィールドは、全てのユーザーに同じ言語のコンテンツを表示してしまいます。内部向けなら問題ないこともありますが、商品説明やメールテンプレートなど外部向けコンテンツでは致命的になり得ます。導入時に設定漏れが起こりやすく、後から修正すると手間がかかります。
プレーンテキストが期待される場所でHtmlを使ってしまうこと
メール件名やレポートタイトル、外部APIのレスポンスなど、プレーンテキストを想定する箇所にHTMLを入れると、タグがそのまま表示されてしまうことがあります。用途に応じてChar/Text/Htmlを使い分け、どのように消費されるかを事前に確認してください。
まとめ
HtmlフィールドはOdooデータモデルの中でも極めて強力なフィールドです。商品説明やメール、求人票、請求書注記などの裏側で働き、追加ツールを使わずに整形されたコンテンツを実現します。
サニタイズ、翻訳、レンダリングコンテキストといった振る舞いを理解することで、適切な場面で適切にHtmlフィールドを使えるようになります。Odoo Studioで簡単に追加する場合も、Pythonでモジュール化する場合も、APIで自動化する場合も、本稿で述べた原則は共通です。
Odooの多くの機能と同様、仕組みを理解すればHtmlフィールド自体はシンプルです。重要なのは正しい用途に配置し、適切な設定で運用することです。
私たちDasoloは、企業がOdooを各部門で導入・最適化するお手伝いをしています。データモデル設計、ワークフローへのカスタムフィールド追加、ビジネスに合わせたモジュール開発まで、幅広く支援可能です。 お気軽にお問い合わせください。 あなたのOdooプロジェクトについてお話ししましょう。