第10章: 制約

:doc:`前の章<09_actions>は、ビジネスロジックをモデルに追加する機能を導入しました。 ボタンをビジネスコードにリンクさせることができますが、ユーザーが不正なデータを入力しないようにするにはどうすればよいでしょうか? 例えば、当社の不動産モジュールでは、ユーザーが負の予想価格を設定することを妨げるものはありません。

Odoo では、自動的に検証された不変数を設定する方法を 2 つ提供しています: Python constraints と :attr:`SQL constraints <odoo.models.Model._sql_constraints> ` 。

SQL

参考: このトピックに関連するドキュメントは モデルPostgreSQL's documentation にあります。

注釈

目標: このセクションの最後には、

  • 金額は(厳密に) 正の値だけを受け付けます。

金額に制限
  • 物件タイプとタグは、一意の名前を持つようにします。

名前の制約

SQL制約は、モデル属性 _sql_constraints で定義されます。この属性には、3つの文字列 (name, sql_definition, message) を含むリストが割り当てられます。 name` は有効なSQL制約名、 sql_definitiontable_constraint の式、messageはエラーメッセージです。

ここ に簡単な例があります。

Exercise

SQL制約を追加してみましょう。

対応するモデルに次の制約を追加します。

  • 想定される物件価格は厳密に正の値でなければなりません

  • 物件売却価格は正の値でなければなりません

  • オファー価格は厳密に正の値でなければなりません

  • 物件タグ名と物件タイプ名は一意でなければなりません

ヒント: Odoo コードベースで unique キーワードで検索し、一意の名前の例を探してみてください。

結果を確認するために、 -u estate オプションを付けてサーバを再起動します。SQL制約の設定を妨げるデータがあるかもしれないことに注意してください。次のようなエラーメッセージが表示されることがあります。

ERROR rd-demo odoo.schema: Table 'estate_property_offer': unable to add constraint 'estate_property_offer_check_price' as CHECK(price > 0)

例えば、オファーの価格がゼロのものがあれば場合、制約を適用できません。新しい制約を適用するためには、問題のあるデータを削除します。

Python

参考: このトピックに関連するドキュメントは、 constrains() にあります。

注釈

目標: このセクションの最後には、期待される価格の90%以下のオファーを受け入れることはできません。

Python制約

SQL制約は、データの一貫性を確保する効率的な方法です。しかし、Pythonコードを必要とするより複雑なチェックを行う必要があるかもしれません。このような場合、Python制約が必要です。

Python制約は constrains() でデコレートされたメソッドとして定義され、レコードセット上で呼び出されます。デコレータはどのフィールドが制約に関与するかを指定します。制約は、これらのフィールドのいずれかが変更されると自動的に評価されます。このメソッドは、その不変性が満たされない場合に例外を発生させることが期待されます。

from odoo.exceptions import ValidationError

...

@api.constrains('date_end')
def _check_date_end(self):
    for record in self:
        if record.date_end < fields.Date.today():
            raise ValidationError("The end date cannot be set in the past")
    # all records passed the test, don't return anything

単純な例は こちら です。

Exercise

Python制約を追加してみましょう。

販売価格が想定価格の90%より低くならないように制約を追加してください。

ヒント: オファーが有効になるまで販売価格はゼロです。これを考慮してチェックを微調整する必要があります。

警告

Always use the float_compare() and float_is_zero() methods from odoo.tools.float_utils when working with floats!

販売価格または想定価格が変更されるたびに、制約がトリガされるようにしてください。

SQL制約は通常、Python制約よりも効率的です。パフォーマンスが重要な場合は、常にPython制約よりもSQLを優先してください。

私たちの不動産モジュールは良い見え始めています. いくつかのビジネスロジックを追加しました, そして今、我々はデータが一貫していることを確認します. しかし、ユーザーインターフェイスはまだ少しラフです。 next chapter でどのように改善できるか見てみましょう。