ODOO 關於 self 及 self 的使用

self 多會出現在這樣幾種情況下

    class AModel(models.Model):
        _name = 'a.model'
        def a_method(self):
            # self can be anything between 0 records and all records in the database
            self.do_operation()
        
        def b_method(self):
            for rec in self:
                rec.do_operation()

在AModel中的 a_method 方法中,self作爲第一個參數傳入。

在odoo源碼中,註釋這樣說:# self可以是數據庫中介於0條記錄和所有記錄之間的任意值。

也就是說,self 是當前類的實例或實例集合,在b_mothod中也可以看出,self是可以遍歷的集合。

我在源碼中還看到了這麼一句:

Methods defined on a model are executed on a recordset, and their ``self`` is a recordset::

意思是:模型上定義的方法,在記錄集上執行,這時它們的"self"是記錄集。


通過b_method方法中,對self的遍歷,也可以確定的是,每一條實例都封裝了當前模型的信息。

在odoo源碼中,我們也許遇見過下面的這種代碼書寫方式:

    def _compute_product_count(self):
        product_data = self.env['lunch.product'].read_group([('category_id', 'in', self.ids)], ['category_id'], ['category_id'])
        data = {product['category_id'][0]: product['category_id_count'] for product in product_data}
        for category in self:
            category.product_count = data.get(category.id, 0)

 在這段代碼中,對self進行了遍歷,每條記錄即爲category,使用category爲模型中的product_count字段直接賦值,這也說明了self中封裝了模型的記錄集。

你可能還看見過這行代碼:

self.cr.execute("UPDATE res_company SET currency_id = %s WHERE id = %s", [self.currency_eur_id, company.id])

這裏self調用了cr遊標,執行了SQL語句,說明self中封裝了cr 信息。

equipment.owner_user_id = self.env.user.id

self調用了self.env.user.id信息,說明self封裝了當前環境。 

當然,self 還封裝了許多信息,比如上下文,感興趣可以用斷點看一下self 的結構。


接下來說說self封裝的常用的env,env 記錄了用戶當前所在位置的環境,比如:

self.env.context.get('not_unlink_on_discard')

可以獲取到當前環境的上下文(是字典結構)。

除此之外,我們可以將當前環境切換到其他環境上,就像這樣:

emp_res = self.env["hr.employee"].search([])

這樣就可以 獲取到 員工 的記錄集合。

根據id 獲取XML的ID :

self.env.ref('base.res_partner_1')

self 常用的ORM API

# 按條件查找出符合的記錄集
self.env["hr.employee"].search(["name","=","ZERONE"])

# 以id搜索過濾,接收參數爲id的列表
res = self.env["hr.employee"].browse([1,2,3])

# 在hr_employee 中創建一條新的記錄
self.env["hr.employee"].create({
    "name":"Zerone",
    ...
})

# 更新記錄數據
self.env["hr.employee"].search([("id","=",1)]).write({"field_1":"xxx"})

# 將已有記錄複製,生成一條新的記錄,在這裏只有屬性copy=True的字段的值纔會被複制,其他的字段值會以默認值或空填充
res_copy = self.self.env["hr.employee"].search(["name","=","ZERONE"]).copy()

# 獲取字段的默認值,包括上下文、用戶默認值和模型本身的默認值。fields是字段列表,可自己定義
@api.model
def default_get(self, fields):
    print(fields)
    rec = super(payment_register, self).default_get(fields)
    ...
    return rec

# 取符合條件的記錄的條數count
notes_count = self.env['note.note'].search_count([('user_id', '=', self.env.uid)])

# 根據傳入的參數,搜索顯示名稱與給定名稱模式匹配的記錄 name_search接收四個參數,但只有第一個是必須的,返回的是符合條件的記錄集
ns_res = self.env['res.partner'].name_search('Vlad', args=[('user_ids.email', 'ilike', 'vlad')])
ns_res = self.env['res.partner'].name_search('Vlad', operator='ilike')
partners = res_partner.name_search('Vlad', limit=1)

# 根據傳入的字段名列表,返回對應的值
self.env['survey.user_input'].browse(answer_own.ids).read(['state'])

# 根據分組字段,返回記錄分組列表
debit_groups = analytic_line_obj.read_group(
    domain=domain + [('amount', '<', 0.0)],
    fields=['account_id', 'currency_id', 'amount'],
    groupby=['account_id', 'currency_id'],
    lazy=False,offset=0, limit=None, orderby=False
)

對於read_group 方法,domain,fields,groupby三個參數是必須的,

domain 是匹配符合條件的記錄集,

fields 是 取出的字段

groupby 是按那些字段什麼排序,按在數組中的順序

lazy 爲true的話,分組只會根據groupby列表中的第一個元素分組,爲false時,根據列表中所有字段排序

orderby 按哪個字段排序,offset limit 是從第offset條,往後取limit條。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章