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