1.model属性
每个对象(即class)一般由字段(变量)和函数组成,每个对象对应着数据库中的一张表,驼峰命名方式
-
models.Model
基础模块,会根据字段和模型名在后台数据库生成对应得表文件
-
models.TransientModel
临时模块,用于弹出信息的临时数据,会在后台生成对应得表,但是表的内容根据配置,一定时间后被清除,不会长时间保存,如向导时用
-
models.AbstractModel
抽象模块,类似于抽象类,常用于继承
2.model字段类型
odoo对象支持的字段类型有
基础:char,text,boolean,integer,float,date,datetime,binary
复杂:selection,function
关系:one2one,many2one,one2many,many2many
3.self
self是什么,目前旧版本中使用的self是对,游标cr,用户id,上下文context,模型,记录集,缓存的封装
可以通过self.xx获取到这些封装得东西,如self.cr,self.uid
在查出来某模型的记录后可以通过record.xx=value来直接修改记录的字段内容,同样在重写模型的write方法
中,也可以通过self.xx=value来指定新增记录中某字段得值
此时注意
a修改查出来的记录字段值来改变数据库内容,是通过改变缓存中的值触发数据库写记录来达到的
b重写write方法是,在write方法中每调用一次self.xx=value语句,都会触发数据库的写操作,因此一般用
1
2
|
for rec in self
rec.xx = xx
|
操作
操作缓存:
环境存储了模型的缓存记录,因此可以通过环境来获取增加,修改,删除记录,而触发数据库更改
从而达到操作数据库的目的
如 新增:
1
|
self .env[ '模型' ].create(vals)
|
访问当前用户:
1
|
self .env.user
|
更新缓存,触发数据库操作
1
|
self .env.invalidate_all()
|
self常用接口
普通查询:返回记录集,后续通过修改记录值来触发数据库修改
1
2
|
self .search(domain) #从当前模型的self中查询
self .env[ 'model' ].search(domain) #获取某个model的环境,查询其中的记录集
|
只读查询:返回列表,只能提取内容,不能触发数据库修改
1
|
self .search_read([],[ '要查询的字段' ])
|
统计数量:返回符合条件的记录条数
1
|
self .search_count(domain)
|
浏览:通过一系列的id值,返回对应得记录集
1
|
self .browse([ id ])
|
删除:
1
|
self .unlink(domain)
|
new ids
odoo在创建一个新纪录时,会使用models.ids虚拟一个记录id,可以通过如下来判断
1
|
if is instance(record. id ,models.NewId)
|
记录集
model的数据是通过数据集的形式来使用的,定义在model里的函数执行时他们的self变量也是一个数据的集合
1
2
3
4
5
6
7
8
9
10
11
|
class AModel(models.Model):
_name = 'a.model'
def a_method( self ): # self can be anywhere between 0 records and all records in the database
self .do_operation()
def do_operation( self ):
print self # => a.model(1, 2, 3, 4, 5)
for record in self :
print record # => a.model(1), then a.model(2), then a.model(3), ...
|
获取有关联的字段(one2many,many2one,many2many)也是返回一个数据集合,如果字段为空则返回空的集合
每个赋值语句都会触发数据库字段更新,同时更新多个字段时可使用或者更新多条记录时使用write函数
1
2
3
4
5
6
7
8
9
10
11
12
|
# 3 * len(records) database updates for record in records:
record.a = 1
record.b = 2
record.c = 3
# len(records) database updates for record in records:
record.write({ 'a' : 1 , 'b' : 2 , 'c' : 3 })
# 1 database update records.write({ 'a' : 1 , 'b' : 2 , 'c' : 3 })
|
-
数据缓存和预读取
odoo会为记录保留一份缓存,他有一种内置的预读取机制,通过缓存来提升性能
集合运算符
record in set 返回record是否在set中,record须为单条记录,record not in set 反之
set1<=set2返回set1是否为set2的子集
set1>=set2返回set2是否为set1的子集
set1|set2返回set1和set2的并集
set1&set2返回set1和set2的交集
set1-set2返回在集合set1中但不在set2的记录
其他集合运算
filtered()返回满足条件的数据集
1
2
3
4
5
|
# only keep records whose company is the current user's records.filtered( lambda r: r.company_id = = user.company_id)
# only keep records whose partner is a company records.filtered( "partner_id.is_company" )
|
sorted()返回根据提供的键排序之后的结果
1
2
|
# sort records by name records. sorted (key = lambda r: r.name)
|
mapped()返回应用了指定函数之后的结果集
1
2
3
4
5
6
7
8
9
|
#returns a list of summing two fields for each record in th set records.mapped( lambda r:r.field1 + r.field2)
#函数也可以是字符串 对应记录的字段 #return a list of names records.mapped( 'name' )
#returns a recordset of partners record.mapped( 'partner_id' )
|
运行环境
运行环境保存了很多ORM相关的变量:数据库查询游标,当前用户,元数据,还有缓存,所有的model数据集都有不可改变的环境变量,可使用env来访问,如records.env.user,records.env.cr,records.env.context,运行环境还可用于为其他模型初始化一个空的集合并对该模型进行查询
1
2
|
self .env[ 'res.partner' ].search([[ 'is_company' , '=' , True ],[ 'customer' , '=' , True ]])
#res.partner(1,2,3,4,5,7,77) |
更改运行环境:可以基于一个运行环境自定义,以得到拥有新运行环境的数据集
sudo()使用现有数据集创建一个新运行环境,得到一个基于新运行环境的数据集的拷贝
1
2
3
4
5
6
|
#create partner object as administrator env[ 'res.partner' ].sudo().create({ 'name' : "A Partner" })
#list partners visible by the "public" user public = env.ref( "base.public_user" )
env[ 'res.partner' ].sudo(public).search([])
|
with_context
一个参数时可用于替换当前运行环境的context,多个参数时通过keyword添加到当前运行环境context或单参数时设置context
with_env()完整替换当前运行环境
常用ORM函数
-
search(domain)
作用:搜索指定domain的记录集,接受domain表达式参数
参数:搜索domain[()]
返回值:符合搜索结果的对象列表,可以通过limit,offset参数返回一个子集,还可以通过order参数对数据排序
1
2
3
4
5
6
7
8
|
self .search([( 'is_company' , '=' , True ),( 'customer' , '=' , True )])
#res.partner(1,2,3,4,5,7,77) self .search([( 'is_company' , '=' , True )],limit = 1 ).name
#'Agrolait' students = self .search[( 'name' , '=' , self .name)]
#查所有与当前名字相同的学员 |
如果只需要知道满足条件的数据数量,可以使用search_count()函数
-
create(val)
接收多个字段,值的组合,返回新创建的数据集
作用:创建对象
参数:要创建的对象字典
返回值:新创建的对象
1
2
3
4
5
6
7
8
9
|
student = self .create({
'name' : '张三'
'age' : 26 ,
'sex' : 'man' ,
'sno' : '1'
}) #创建了一个新学员 self .create({ 'name' : 'new name' })
|
write(val)接收多个字段,值组合,会对指定数据集的所有记录进行修改,不返回
作用:修改对象
参数:需要修改参数的字典
1
|
self .write({ 'name' : 'new name' })
|
browse(ids)根据数据的id或者一组id来查找,返回符合条件的数据集合
作用:获取指定记录的对象
参数:记录值的ids
返回值:对象列表
browse方法其实在v7版本中应用的更多,因为v7版本的search等方法返回值是ids,而v8版本中的返回值已经是目标对象的列表了,因此就不需要再次调用browse方法
1
2
3
4
|
sale_order = self .env[ 'sale.order' ].browse( 1 ) #获取数据库中id为1的销售订单
self .browsw([ 7 , 8 , 12 ])
res.partner( 7 , 8 , 12 )
|
unlink()
作用:删除记录
1
|
self .unlink
|
对于v7版本每种方法都需要添加cr,uid,ids,context等几个参数
exists()得到某个数据集中保留在数据库中的那部分,或在对一个数据集进行处理后重新赋值
1
2
3
4
5
6
|
if not record.exists():
raise Exception( 'The record has been deleted' )
records.may_remove_dome() #only keep records which were not deleted records = records.exists()
|
ref()运行环境函数根据提供的external id返回对应得数据记录
1
2
|
env.ref( 'base.group_public' )
res.groups( 2 )
|
ensure_one()检验某个数据集是否只包含单条数据,若不是则报错
1
2
3
|
records.ensure_one() #和下面语句效果相同 assert len (records) = = 1 , 'Expected singleton'
|