odoo ORM API
基于odoo 12.0
odoo中的模型,一个很重要的特点就是,它即是定义模型的类,又是数据记录的集合,这一特性可以很方便的在模型中直接定义数据记录集的操作。例如赋值、修改、删除、计算等等。这些特性都需要odoo提供的ORM API来实现,具体方式是在函数定义前加上API的装饰器。
常用装饰器
-
@api.one:表示确定只有一条记录,模型类函数中self代表一条数据集,可直接采用self.<字段名>进行增查改删的操作吗,但是官方不提倡使用api.one装饰器
-
@api.multi:表示多条记录,此时函数的self代表的是一个数据集,通常可采用 for record in self 来循环对数据集操作,也可以使用self.ensure_one()函数达到api.one的目的。
-
@api.model:类装饰器,这里的self就不再是数据集,而是类本身,相当于python中的@classmethod,@api.model装饰器不能用于按钮的点击操作逻辑函数,应使用api.multi
-
@api.depends:用于计算字段,形式为@api.depends(‘field1’,‘field2’…),用于标示哪些字段参与了计算字段的计算,同时函数内计算字段必须被赋值,否则会报错
-
@api.constraints:用于评估和检查,使用形式同@api.depends,若记录修改时,检查不通过,则不会修改记录
-
@api.onchange:用于用户在交互时自动更新关联字段,self指的是一条记录,可返回一个报告修改信息字典{‘title’:‘message title’,‘message’:‘message body’}
ORM方法
orm操作数据集
- 基本方法
- <model>.create(values) :增
- <model>.write(values) :改
- <model>.unlink():删
这三种模型写入数据的操作是models.Model自带的函数,用户可以根据需要重写该方法
- shell命令
启动odoo的shell调试器(需要安装watchdog包),在终端输出以下命令进入shell:
进入shell后,输入命令:odoo-bin shell -d (数据库名) -c /etc/odoo/odoo.conf #ubuntu or debian系统 python odoo-bin shell -d (数据库名) #windows系统
shell中的self即为管理员账户,shell中可以通过env函数查询数据集:>>>self res.users(1,) >>>self._name 'res.users' >>>self.name 'Administrator'
self.env种包含了如下几个属性:>>>self.env['res.users'].search([],limit=1)#通过模块名查找,如果不加limit=1,返回结果是一个列表 res.users(1,) >>>self.env['sale.order'].browse()#通过模块名查找 res.users(1,) >>>self.env.ref('base.user_root')#通过外部ID查找 res.users(1,)
- env.cr 当前数据库光标
- env.user 当前会话用户的记录
- env.uid 当前会话用户的ID,相当于env.user.id
- env.context 会话的上下文不可变字典
- env.sudo(user) 通过参数指定的用户返回用户所属的环境信息,如果不传参,默认返回管理员账户的环境
- env.with_context(dict) 可以使用参数中的字典中的值给上下文环境中的值替换
- env.with_context(key=value……) 同上
事务底层SQL
通过ORM API来执行数据库相关的操作:
self.env.cr.execute(sql) #直接执行sql语句
self.env.cr.commit() #用于提交本次事物
self.env.cr.savepoint() #设置一个保存点用于回滚(rollback)
self.env.cr.rollback() #取消当前操作,回滚到上次提交的点或者上一个保存点
示例:
>>>self.env.cr.execute('select id,login from res_users where login=%s or id=%s'.format('demo',1))
>>>self.env.cr.fetchall()
[(1,'admin'),(5,'demo')]
使用方法与其他的数据库orm api(pymysql,pyodbc等)类似。
此外,还可以运行数据库操作命令(DML),但odoo保存的是数据缓存,与数据库中的数据可能会不一致,因此在使用原是DML时,应该在完成后使用self.env.invalidate_all()清空这些缓存。
记录集的使用
- context
context是用字典储存的会话数据,在前端和服务器端都可以使用
前端中,context可以叫信息从一个视图传递给另外一个视图,比如上一个窗体记录的ID,在俺就点击动作完成后传递给下一个窗体。
{'lan':'en_US','tz':'Europe/Brussels','uid':1}
服务器端,记录集可的字段值可以依赖context提供的本地设置,为服务器端提供一些信号信息。
当从一个窗体通过点击一个俺就打开另一个窗体时,关键字active_id(active_ids)将会加载到context中,记录了上一个窗体定位的记录id。active_model则记录的视图模型的技术名称。这在业务向导中经常用到。
例如在向导中要获取上一个记录的记录集,在对筛选的记录集在下一个窗体进行操作。实现过程为:在按钮的点击事件函数中,通过需要用到default_get()方法
@api.model
def default_get(self,feild_names):
defaults = super(ModelClass,self).default_get(feild_names)
defaults['ids'] = self.env.context('active_ids')
return defaults
context在客户端可以用来设置目标视图的默认值或激活默认筛选器,使用default_或者default_search_开头的关键字来完成这种设置。
{‘default_user_id’:uid}
{‘default_search_filter_res_users’:1}
- domain
domain用于筛选记录集,domain使用的为domain表达式,形式为一个条件列表,每个条件都是一个元祖,如:
[('is_done','=',False)] #[(<字段名>,<比较符>,<值>)]
使用时需注意:
- 客户端使用时,当前视图的字段时可用,但不能使用点(.)连接这些字段使用
- 服务器端使用时,可以通过点连接
- 通常的比较符:<,>,<=,>=,=,!=
- =like:匹配模式,_表示任意字符,%表示任意字符串
- like:匹配模式,%value%
- child of:筛选子节点的值
- in和not in:包含不包含
- 与或非:使用’&’、’|’、’!‘一个或两个条件元祖构成,如[’&’,A,B]代表A&B,[’|’,A,B]代表A|B,多个与或非构成表达式,从后向前进行计算。
记录集的操作
查询模式
- search方法,可以传递domain表达式进行筛选查询,其他参数还有order、limit及offset,分表代表对应的sql语句
- browse方法:返回记录集的IDs或单个ID的列表方法。
- search_count方法:只返回计数
- name_search(): many2one字段搜索时调用
- search_read(): many2one点开搜索更多时调用
- read_group(): 搜索视图分组时调用
单例模式
只有一个记录的记录集成为单例,空记录也是单例。
对于单例模式,在开始时使用self.ensure_one()
写记录集
- create方法:创建记录,传入字典参数
- unlink方法:删除记录,不传入参数,直接用记录集调用
- write方法:修改记录,传入字典参数
日期和时间
from odoo import fields
fields.Datetime.now() ##时间
fields.Datetime.from_string('2018-01-01 00:00:00')
fields.Datet.today() ##日期
操作记录集
record是一个记录集,可以对其进行一下操作
- x in record 遍历记录集
- x not in record 遍历记录集的他集
- record.ids 返回记录集的id李彪
- record.ensure_one() 返回单例记录集
- record.filtered(func) 返回经过筛选的记录集
- record.mapped(func) 返回经过映射值得列表
- record.sorted(func) 返回有序的记录集
非单例的记录集为一个列表,在服务器端可通过列表的方式进行操作
关系字段
- 多对一、多对多:one_record.many_ids
- 一对多: one_record.one_id