第11章:約束?

前一章節 (tutorials/getting_started/10_actions) 介紹了如何在模型中添加業務邏輯?,F在我們可以將按鈕鏈接到業務代碼,但是如何防止用戶輸入不正確的數據呢?例如,在我們的房地產模塊中,沒有任何東西可以防止用戶設置負的預期價格。

Odoo提供了兩種設置自動驗證不變量的方法: Python約束SQL約束 。

SQL?

參考 : 有關此主題的文檔可以在 模型PostgreSQL文檔 中找到。

注解

目標 :本節結束時:

  • 金額應該是(嚴格)正數

金額限制
  • 屬性類型和標簽應該有唯一的名稱

名稱的限制條件

SQL約束通過模型屬性 _sql_constraints 定義。該屬性被賦予一個三元組列表,包含字符串 (name, sql_definition, message) ,其中 name 是一個有效的SQL約束名, sql_definition 是一個table_constraint_表達式, message 是錯誤信息。

你可以在 這里 找到一個簡單的例子。

Exercise

添加 SQL 約束。

將以下約束條件添加到相應的模型中:

  • 物業預期價格必須嚴格為正數

  • 房產銷售價格必須為正數

  • 報價必須嚴格為正數

  • 屬性標簽名稱和屬性類型名稱必須唯一

提示:在Odoo代碼庫中搜索“unique”關鍵字以查找唯一名稱的示例。

使用 -u estate 選項重新啟動服務器以查看結果。請注意,您可能有數據阻止 SQL 約束的設置??赡軙棾鲱愃埔韵洛e誤消息的消息框:

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%。

提示:在報價被驗證之前,銷售價格為零。您需要微調您的檢查以考慮這一點。

警告

在處理浮點數時,務必使用 odoo.tools.float_utils 中的 float_compare()float_is_zero() 方法!

確保每次銷售價格或預期價格發生變化時都會觸發約束條件!

SQL約束通常比Python約束更有效。當性能很重要時,始終優先選擇SQL而不是Python約束。

我們的房地產模塊看起來不錯。我們添加了一些業務邏輯,現在確保數據一致性。然而,用戶界面還有些粗糙。讓我們看看如何在 下一章節 中改進它。