recordsets
模型和记录的交互通过记录集来进行,记录集是同一模型的一系列记录的排序
注意:
与名称的含义不同,记录集在当前情况下有可能重复,以后可能会改变
模型上定义的方法在记录集上执行,self本身也是一个记录集:
class AModel(models.Model):
_name = 'a.model'
def a_method(self):
# self可以是第0个记录和全部记录任意一个
self.do_operation()
迭代一个记录集可以产生单个记录的集合,就像遍历字符串会拿到单个字符一样
def do_operation(self):
print self # => (1, 2, 3, 4, 5)
for record in self:
print record # 1, 2, 3, 4, 5
字段的访问
记录集提供了一个“活动记录”接口:模型字段可以直接从记录读取和写入,但只能在单例(单记录集)上。设置字段值将触发对数据库的更新
在多条数据的记录集上读或者写将会抛出错误
如果关系字段不为空(Many2one,One2many,Many2many),访问关系字段总是会获得一个记录集
每个字段的赋值都会触发数据库的更新,当一次性在单个记录上赋值多个字段或者在记录集上赋值多个字段时,应该使用write()
for record in records:
record.a = 1
record.b = 2
record.c = 3
for record in records:
record.write({'a': 1, 'b': 2, 'c': 3})
records.write({'a': 1, 'b': 2, 'c': 3})
记录集的运算
记录集是不可变的,但是同一个模型的集合可以使用不同的集合操作组合,返回新的记录集。集合操作不保存顺序。
- record in set 返回记录是否在集合中(record not in set)
- set1 <= set2 和 set1 < set2返回集合set1是否是set2的子集
- set1 >= set2 和 set1 > set2返回集合set1是否是set2的父集
- set1 | set2 返回并集的集合
- set1 & set2 返回交集的集合
- set1 - set2 返回差集的集合
其它的记录集操作
记录集是可迭代的,所以通常的Python工具可以用于转换(map(), sort (), ifilter(),…),但是这些返回列表或迭代器,删除了对结果调用方法或使用集合操作的能力。
记录集提供这些操作返回记录集本身(如果可能的话)
filtered()
返回只包含满足所提供谓词函数的记录集。谓词也可以是一个字符串,通过字段为真或假进行筛选
records.filtered(lambda r: r.company_id == user.company_id)
records.filtered("partner_id.is_company")
sorted()
返回根据提供的键函数排序的记录集。如果没有提供键,使用模型的默认排序顺序
# 通过名字排序
records.sorted(key=lambda r: r.name)
mapped()
将提供的函数应用于记录集中的每个记录,如果结果是记录集,则返回一个记录集
# 返回记录集中记录的两个字段拼接后的列表
records.mapped(lambda r: r.field1 + r.field2)
提供的函数可以是字符串来获取字段值
records.mapped('name')
record.mapped('partner_id')
# 返回银行编号的列表,并去重
record.mapped('partner_id.bank_ids')
Environment
环境存储ORM使用的各种上下文数据:数据库游标(用于数据库查询)、当前用户(用于访问权限检查)和当前上下文(存储任意元数据)。环境还存储缓存。
所有记录集都有一个环境,它是不可变的,可以使用env访问,并提供对当前用户(用户)、游标(cr)或上下文(上下文)的访问:
>>> records.env
<Environment object ...>
>>> records.env.user
res.user(3)
>>> records.env.cr
<Cursor object ...)
从其他记录集中创建记录集时,环境将被继承。该环境可用于在其他模型中获取空记录集,并查询该模型
>>> self.env['res.partner']
res.partner
>>> self.env['res.partner'].search([['is_company', '=', True], ['customer', '=', True]])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)
改变环境
可以从记录集中定制环境。这将返回使用已更改环境的记录集的新版本。
sudo()
使用提供的用户集创建新环境,如果没有提供(在安全的上下文中绕过访问权限/规则),则使用管理员,返回使用新环境时调用的记录集的副本:
# 创建合作伙伴对象作为管理员
env['res.partner'].sudo().create({'name': "A Partner"})
# 列出“公共”用户可见的合作伙伴
public = env.ref('base.public_user')
env['res.partner'].sudo(public).search([])
with_context()
1.可以使用单个位置参数来替换当前环境的上下文吗
2.是否可以通过关键字获取任意数量的参数,这些参数可以添加到当前环境的上下文或第1步中设置的上下文
# 寻找合作伙伴,或者如果没有找到合作伙伴,创建一个指定时区的合作伙伴
env['res.partner'].with_context(tz=a_tz).find_or_create(email_address)
with_env()
完全替代现有环境
通用的ORM方法
search()
获取搜索域,返回匹配记录集。可以返回匹配记录的子集(偏移量和极限参数)和order (order参数)
>>> # 搜索当前模型
>>> self.search([('is_company', '=', True), ('customer', '=', True)])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)
>>> self.search([('is_company', '=', True)], limit=1).name
'Agrolait'
Tip
要检查任何记录是否与某个域匹配,或计算执行该操作的记录的数量,可以使用search_count()
create()
获取多个字段值,并返回包含所创建记录的记录集
>>> self.create({'name': "New Name"})
res.partner(78)
write()
获取多个字段值,将其写入记录集中的所有记录。不返回任何内容
self.write({'name': "Newer Name"})
browse()
获取数据库id或id列表并返回一个记录集,当从外部Odoo获取记录id(例如通过外部系统的往返)或在旧API中调用方法时,该记录集非常有用
>>> self.browse([7, 18, 12])
res.partner(7, 18, 12)
exists()
返回一个仅包含数据库中存在的记录的新记录集。可用于检查记录(如从外部获得的)是否仍然存在
if not record.exists():
raise Exception("The record has been deleted")
或者在调用一个可能删除了一些记录的方法之后
records.may_remove_some()
# 只保留没有删除的记录
records = records.exists()
ref()
环境方法返回与提供的外部id匹配的记录
>>> env.ref('base.group_public')
res.groups(2)
ensure_one()
检查记录集是否为单例(仅包含一条记录),否则会引发错误
records.ensure_one()
# 等于:
assert len(records) == 1, "Expected singleton"