前言
在odoo的ORM創(chuàng)建數(shù)據(jù)字段的過程中半等,我們會經(jīng)常需要定義一些字段用來計算某一些字段只和或其他計算結(jié)果蜈缤。
今天介紹一個很好用的方法compute計算屬性
拾氓,這個方法其實是屬于寫在odoo fields中的屬性,但是因為非常常用底哥,還涉及ORM中的方法所以今天就單獨列出來詳細講解它的用法咙鞍。
如何使用odoo compute屬性實現(xiàn)自動計算字段
我們看下面的案例房官。
class FandxProduct(models.Model):
_name = "fandx.product"
name = fields.Char("產(chǎn)品名稱")
nums = fields.Integer("數(shù)量")
unit_price = fields.Float("產(chǎn)品單位價格")
現(xiàn)在有個需求,這是一個產(chǎn)品表续滋,我們需要計算他的每一個產(chǎn)品的總價格(產(chǎn)品單位價格*數(shù)量)翰守,這時候就要用到我們的主角compute屬性,下面看案例疲酌。
class FandxProduct(models.Model):
_name = "fandx.product"
name = fields.Char("產(chǎn)品名稱")
nums = fields.Integer("數(shù)量")
unit_price = fields.Float("產(chǎn)品單位價格")
# 使用_compute_all_price
all_price = fields.Float("產(chǎn)品總價格", compute="_compute_all_price")
def _compute_all_price(self):
# self取值默認是multi蜡峰,所以需要循環(huán)拿到每一個record的值
for record in self:
# 計算每一個record的all_price的值進行賦值
record.all_price = record.unit_price * record.nums
在字段中定義屬性compute并指向計算方法,在數(shù)據(jù)創(chuàng)建的時候會自動計算這個字段的數(shù)據(jù)朗恳。
這樣我們在XML中使用all_price就可以獲取到產(chǎn)品的總價格湿颅,但是這里還有一個問題。
數(shù)據(jù)庫中是沒有進行持久存儲的粥诫,那么數(shù)據(jù)數(shù)據(jù)量一大油航,每次渲染頁面都要進行計算,這樣是非常消耗服務(wù)器性能的臀脏,所以我們就要將計算的字段給存儲起來。
如何存儲odoo compute計算字段的值
方法很簡單冀自,只需要在定義的field中加上store字段揉稚,這樣就會把計算到的結(jié)果給存儲到數(shù)據(jù)庫中。
class FandxProduct(models.Model):
_name = "fandx.product"
name = fields.Char("產(chǎn)品名稱")
nums = fields.Integer("數(shù)量")
unit_price = fields.Float("產(chǎn)品單位價格")
# 使用_compute_all_price
# 在字段中加上store = True實現(xiàn)數(shù)據(jù)的持久化
all_price = fields.Float("產(chǎn)品總價格", compute="_compute_all_price", store=True)
def _compute_all_price(self):
# self取值默認是multi熬粗,所以需要循環(huán)拿到每一個record的值
for record in self:
# 計算每一個record的all_price的值進行賦值
record.all_price = record.unit_price * record.nums
這樣我們在數(shù)據(jù)庫中就有了all_price的字段來記錄產(chǎn)品總價格搀玖。
但是現(xiàn)在又出現(xiàn)一個問題,計算字段是計算出了我們的結(jié)果驻呐,但是如果nums改變灌诅,或者unit_price改變了,計算字段并不會改變怎么辦含末!
compute配合使用depends監(jiān)聽數(shù)據(jù)變化
class FandxProduct(models.Model):
_name = "fandx.product"
name = fields.Char("產(chǎn)品名稱")
nums = fields.Integer("數(shù)量")
unit_price = fields.Float("產(chǎn)品單位價格")
# 使用_compute_all_price
# 在字段中加上store = True實現(xiàn)數(shù)據(jù)的持久化
all_price = fields.Float("產(chǎn)品總價格", compute="_compute_all_price", store=True)
# 將nums猜拾、unit_price字段進行監(jiān)聽,在數(shù)據(jù)變動的時候再次執(zhí)行compute指向的方法進行重新賦值計算佣盒。
@api.depends('nums', 'unit_price')
def _compute_all_price(self):
# self取值默認是multi挎袜,所以需要循環(huán)拿到每一個record的值
for record in self:
# 計算每一個record的all_price的值進行賦值
record.all_price = record.unit_price * record.nums
到這里就基本實現(xiàn)了compute的所有經(jīng)常使用的方法,下面一般會配合compute一起使用的屬性inverse
肥惭。
odoo中逆向計算inverse屬性使用詳解
上面講解了compute方法是用來計算對應(yīng)的數(shù)據(jù)字段的盯仪。
inverse方法其實就是compute的逆向方法,默認情況下xml中對應(yīng)的compute計算字段是readonly的蜜葱。
當(dāng)我們加上inverse逆向計算的時候全景,那么就可以在XML中輸入對應(yīng)的值,然后系統(tǒng)會走inverse對應(yīng)的方法牵囤。
class FandxProduct(models.Model):
_name = "fandx.product"
name = fields.Char("產(chǎn)品名稱")
nums = fields.Integer("數(shù)量")
unit_price = fields.Float("產(chǎn)品單位價格")
# 使用_compute_all_price
# 在字段中加上store = True實現(xiàn)數(shù)據(jù)的持久化
all_price = fields.Float("產(chǎn)品總價格", compute="_compute_all_price", inverse='_set_unit_price', store=True)
# 將nums爸黄、unit_price字段進行監(jiān)聽滞伟,在數(shù)據(jù)變動的時候再次執(zhí)行compute指向的方法進行重新賦值計算。
@api.depends('nums', 'unit_price')
def _compute_all_price(self):
# self取值默認是multi馆纳,所以需要循環(huán)拿到每一個record的值
for record in self:
# 計算每一個record的all_price的值進行賦值
record.all_price = record.unit_price * record.nums
def _set_unit_price(self):
for record in self:
if not all([record.nums, record.all_price]):
continue
# 當(dāng)我們手動修改all_price的值的時候诗良,我們就可以逆向去計算出unit_price的值,進行重新賦值鲁驶。
record.unit_price = record.all_price / record.nums
總結(jié)
- odoo的compute可以實現(xiàn)我們對數(shù)據(jù)字段自動計算的需求鉴裹。
- fields中加入store屬性可以實現(xiàn)數(shù)據(jù)的持久化存儲。
- compute計算字段在持久化存儲之后不會在自動計算钥弯,需要我們配合depends來監(jiān)聽指定計算字段在數(shù)據(jù)改動的時候重新計算數(shù)據(jù)字段径荔。
- inverse方法可以幫助我們解決compute計算字段readonly的問題,并在輸入對應(yīng)的字段進行逆向計算之前的字段脆霎。
- compute字段默認是store為False的所有search是無效的总处,還可以指定search的方式實現(xiàn)搜索。這里就不去細講了睛蛛,很簡單也不常用鹦马。
- 還有compute_sudo屬性可以設(shè)置字段在使用的時候是否以超級管理員的方式來進行計算,這里store=True的時候默認為True忆肾,否則默認為False荸频,了解一下就可以了。
- 如果有問題可以在下方留言客冈。