在很多場景下,需要對用戶輸入數據進行驗證。比如編碼不能重復,郵箱的準確性,手機號碼規則,凡是不符合這些驗證規則的數據,要報錯并拒絕保存。在odoo中使用constraints(約束)來實現。odoo提供兩種方式實現自動驗證,python constraints和sql constraints
sql constraints
_sql_constraints = [
('name_description_check',
'CHECK(name != description)',
"名稱和描述不能相同"),
('name_unique',
'UNIQUE(name)',
"已存在相同名稱"),
]
sql constraints 通過模塊屬性_sql_constraints 進行定義。它是一個元組的列表,每個元組是一條數據約束(name, sql_definition, message),包含三個字符串元素:1)約束名稱;2)約束規則(postgresql約束規則);3)違反約束規則時的警告信息。
注意,使用sql constraints,需要確保當前數據庫里面沒有違反該約束的數據,如果數據庫中存在有違反約束的記錄,那么在更新模塊的時候系統日志里面會有警告信息并且constraints會添加失敗。
python constraints
from odoo.exceptions import ValidationError
@api.constrains('age')
def _check_something(self):
for record in self:
if record.age > 20:
raise ValidationError("Your record is too old: %s" % record.age)
# all records passed the test, don't return anything
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
for r in self:
if r.instructor_id and r.instructor_id in r.attendee_ids:
raise exceptions.ValidationError("A session's instructor can't be an attendee")
python constraints,是通過裝飾器@api.constrains(field_name,)來定義,每次記錄修改的時候,如果包含裝飾器定義的字段就會觸發下面的方法,所以需要在方法里面判斷是否違反約束,如果違反,則通過raise異常來彈出警告框并阻止記錄保存。使用python constraints的時候就算是系統內已經有違反約束的記錄也可以對新記錄生效,并且里面的判斷可以添加更加復雜的邏輯。
總的來說,sql constraints的效率較高,而python constraints使用更加靈活。