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

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