1. 程式人生 > WINDOWS開發 >odoo開發中@api.depends與@api.onchange的區別

odoo開發中@api.depends與@api.onchange的區別

@api.depends

這個裝飾器主要運用在odoo的欄位相關的函式中。在函式中,對該欄位值進行處理時,如果計算值依賴於其他相關欄位,不論是與該欄位隸屬同一張表的還是其他表的欄位,都會觸發所編寫的欄位函式。正因為此,可以利用@api.depends 裝飾來偵測與欄位相關的其他表的欄位。如果decorator中依賴的任何欄位“被ORM更改或在表單中更改”,都將觸發對decorated函式的呼叫。

@api.onchange

這個裝飾器觸發decorated函式的時機是:定義的指定欄位如果在form窗體出現了變化,就會觸發執行。這裡要注意的是,這些欄位是隸屬於同一個模型或同一介面。

綜上,雖然@api.depends 與@api.onchange有諸多相似的地方,但一個重要區別就是 onchange 的偵測欄位範圍需要在同一個模型或介面上;而depends 可以偵測關聯的模型的欄位(可以跨不同表)。

    @api.onchange(product_uom_qty,product_uom,route_id)
    def _onchange_product_id_check_availability(self):
        if not self.product_id or not self.product_uom_qty or not self.product_uom:
            self.product_packaging 
= False return {} if self.product_id.type == product: precision = self.env[decimal.precision].precision_get(Product Unit of Measure) product = self.product_id.with_context( warehouse=self.order_id.warehouse_id.id,lang=self.order_id.partner_id.lang or
self.env.user.lang or en_US )

上面這段程式碼節選自sale_order.py 檔案SaleOrderLine類中,‘product_uom_qty‘,‘product_uom‘,‘route_id‘ 這些欄位都是定義在sale.order.line 模型中的。

再看下面程式碼中用到的depends:

class SaleOrderLine(models.Model):
    _inherit = sale.order.line

    qty_delivered_method = fields.Selection(selection_add=[(stock_move,Stock Moves)])
    product_packaging = fields.Many2one(product.packaging,string=Package,default=False)
    route_id = fields.Many2one(stock.location.route,string=Route,domain=[(sale_selectable,=,True)],ondelete=restrict)
    move_ids = fields.One2many(stock.move,sale_line_id,string=Stock Moves)

    @api.multi
    @api.depends(product_id)
    def _compute_qty_delivered_method(self):
        """ Stock module compute delivered qty for product [(‘type‘,‘in‘,[‘consu‘,‘product‘])]
            For SO line coming from expense,no picking should be generate: we don‘t manage stock for
            thoses lines,even if the product is a storable.
        """
        super(SaleOrderLine,self)._compute_qty_delivered_method()

        for line in self:
            if not line.is_expense and line.product_id.type in [consu,product]:
                line.qty_delivered_method = stock_move

    @api.multi
    @api.depends(move_ids.state,move_ids.scrapped,move_ids.product_uom_qty,move_ids.product_uom)
    def _compute_qty_delivered(self):
        super(SaleOrderLine,self)._compute_qty_delivered()

這段程式碼與上面onchange片段一樣都來自SaleOrderLine類,但可以看到 @api.depends(‘product_id‘) 中的product_id欄位是不在sale.order.line模型中的。同樣,@api.depends(‘move_ids.state‘,‘move_ids.scrapped‘,‘move_ids.product_uom_qty‘,‘move_ids.product_uom‘) 也是跨表偵測欄位。

從上面兩段程式碼,就能看出兩者最主要的區別,另外從觸發來看,api.onchage在欄位變化的時候會觸發一次,當欄位內容變換完成儲存的時候還會觸發一次。而api.depends則只在欄位變化的時候觸發一次。