“ORM参考”的版本间的差异

来自Odoo大V社-odoo中文开发手册
跳转至: 导航搜索
 
(未显示同一用户的4个中间版本)
第1行: 第1行:
 +
==记录集(RecordSet)==
 +
模型和记录的交互通过记录集(同一模型的一组有序记录)进行。
 +
提示
 +
与名称暗示相反,记录集可能包含重复数据。这可能会在将来更改完善。
 +
在模型上定义的方法在记录集上执行,它们的self是记录集:
 +
<nowiki>
 +
Class AModel(models.Model):
 +
    _name ='a.model'
 +
    def a_method(self):
 +
        #self可以在0个记录和所有记录之间的任何地方
 +
        #数据库
 +
        self.do_operation()
 +
</nowiki>
 +
在记录集上迭代将产生一组单个记录(“singletons”),很像在Python字符串上迭代产生单个字符的字符串:
 +
<nowiki>
 +
def do_operation(self):
 +
    print self            #=> a.model(1,2,3,4,5)
 +
    for record in self:
 +
        print self        #=> a.model(1),然后a.model(2),然后a.model(3),...
 +
</nowiki>
 +
==字段访问==
 +
记录集提供了一个“活动记录”接口:模型字段可以直接从记录中读取和写入,但只能在单例记录集(单记录记录集)上读取和写入。设置字段的值将触发对数据库的更新:
 +
<nowiki>
 +
>>> record.name
 +
示例名称  #返回 record 记录 name 字段的值
 +
>>> record.company_id.name
 +
公司名    #返回公司名称
 +
>>> record.name =“Bob”
 +
</nowiki>
 +
尝试在多个记录上读取或写入字段将引发错误。
 +
访问关系字段(Many2one,One2many,Many2many)总是返回记录集,如果未设置字段,则为空。
 +
<nowiki>
 +
危险
 +
每个对字段的赋值触发数据库更新,在同时设置多个字段或在多个记录上设置字段(使用相同的值)时,请使用write():
 +
#3 * len(records)次数据库更新
 +
for record in records:
 +
    record.a = 1
 +
    record.b = 2
 +
    record.c = 3
 +
#len(records)次数据库更新
 +
for record in records:
 +
    record.write({'a':1,'b':2,'c':3})
 +
 +
#1次数据库更新
 +
records.write({'a':1,'b':2,'c':3})
 +
</nowiki>
 +
==记录缓存和预取==
 
Odoo为记录的字段维护一个缓存,所以不是每个字段访问都会发出一个数据库请求,这对性能来说是可怕的。以下示例仅对第一条语句查询数据库:
 
Odoo为记录的字段维护一个缓存,所以不是每个字段访问都会发出一个数据库请求,这对性能来说是可怕的。以下示例仅对第一条语句查询数据库:
record.name#首次访问从数据库读取值
+
record.name#首次访问从数据库读取值
record.name#second access从缓存获取值
+
record.name#second access从缓存获取值
为了避免一次读取一个记录上的一个字段,Odoo根据一些启发式方法预取记录和字段以获得良好的性能。一旦必须在给定记录上读取字段,ORM实际上在较大的记录集上读取该字段,并将返回的值存储在高速缓存中供以后使用。预取的记录集通常是记录从中通过迭代而来的记录集。此外,所有简单存储的字段(布尔,整数,浮点,字符,文本,日期,日期时间,选择,许多2)它们对应于模型表的列,并在同一查询中有效地提取。
+
为了避免一次读取一个记录上的一个字段,Odoo根据一些启发式方法预取记录和字段以获得良好的性能。一旦必须在给定记录上读取字段,ORM实际上在较大的记录集上读取该字段,并将返回的值存储在高速缓存中供以后使用。预取的记录集通常是记录从中通过迭代而来的记录集。此外,所有简单存储的字段(boolean, integer, float, char, text, date, datetime, selection, many2one)它们对应于模型表的列,并在同一查询中有效地提取。
 
考虑下面的示例,其中partners是1000条记录的记录集。没有预取,循环将对数据库进行2000次查询。使用预取,只进行一个查询:
 
考虑下面的示例,其中partners是1000条记录的记录集。没有预取,循环将对数据库进行2000次查询。使用预取,只进行一个查询:
合作伙伴:
+
<nowiki>
     print partner.name#first pass prefetches'name''lang'
+
for partner in partners:
                                 所有“合作伙伴”上的#(和其他字段)
+
     print partner.name          # first pass prefetches 'name' and 'lang'
     打印partner.lang
+
                                 # (and other fields) on all 'partners'
 +
     print partner.lang
 +
</nowiki>
 
预取也对辅助记录起作用:当读取关系字段时,它们的值(它们是记录)被预订用于将来的预取。访问这些辅助记录之一会从同一模型预取所有辅助记录。这使得以下示例只生成两个查询,一个用于合作伙伴,一个用于国家/地区:
 
预取也对辅助记录起作用:当读取关系字段时,它们的值(它们是记录)被预订用于将来的预取。访问这些辅助记录之一会从同一模型预取所有辅助记录。这使得以下示例只生成两个查询,一个用于合作伙伴,一个用于国家/地区:
countries = set()
+
<nowiki>
合作伙伴:
+
countries = set()
     country = partner.country_id#first pass预取所有合作伙伴
+
for partner in partners:
     countries.add(country.name)#首次通过预取所有国家
+
     country = partner.country_id        # first pass prefetches all partners
设置操作
+
     countries.add(country.name)        # first pass prefetches all countries
记录集是不可变的,但是可以使用各种集合操作来组合相同模型的集合,返回新的记录集。设置操作不保留顺序。
+
</nowiki>
record in set返回是否在集合中存在记录(必须是1元素记录集)。记录不在集合中是反向操作
+
==集合操作==
set1 <= set2和set1 <set2返回set1是否为set2的子集(分别为strict)
+
记录集是不可变的,但是可以使用各种集合操作来组合相同模型的集合,返回新的记录集。集合操作不保留顺序。
set1> = set2和set1> set2返回set1是否为set2的超集(相应的严格)
+
<nowiki>
set1 | set2返回两个记录集的并集,新记录集包含任何源中存在的所有记录
+
record in set returns whether record (which must be a 1-element recordset) is present in set. record not in set is the inverse operation
set1&set2返回两个记录集的交集,一个新记录集只包含两个源中都存在的记录
+
set1 <= set2 and set1 < set2 return whether set1 is a subset of set2 (resp. strict)
set1 - set2返回一个只包含不在set2中的set1记录的新记录集
+
set1 >= set2 and set1 > set2 return whether set1 is a superset of set2 (resp. strict)
其他记录集操作
+
set1 | set2 returns the union of the two recordsets, a new recordset containing all records present in either source
记录集是可迭代的,所以通常的Python工具可用于转换(map(),sorted(),ifilter(),...),但是这些返回一个列表或迭代器,取消调用方法的能力,以使用设置操作。
+
set1 & set2 returns the intersection of two recordsets, a new recordset containing only records present in both sources
因此,记录集提供返回记录集的这些操作(如果可能):
+
set1 - set2 returns a new recordset containing only records of set1 which are not in set2
filtered()
+
</nowiki>
返回仅包含满足提供的谓词函数的记录的记录集。谓词也可以是一个字符串,按字段进行过滤:true或false:
+
==其他记录集操作==
#只保留公司是当前用户的记录
+
记录集是可迭代的,所以通常的Python工具可用于
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')
+
环境
+
环境存储ORM使用的各种上下文数据:数据库游标(用于数据库查询),当前用户(用于访问权限检查)和当前上下文(存储任意元数据)。环境还存储高速缓存。
+
所有记录集都有一个环境,它是不可变的,可以使用env访问,并允许访问当前用户(用户),游标(cr)或上下文(上下文):
+
>>> records.env
+
<环境对象...>
+
>>> records.env.user
+
用户(3)
+
>>> records.env.cr
+
<Cursor object ...)
+
从其他记录集创建记录集时,将继承环境。该环境可用于在其他模型中获取空记录集,并查询该模型:
+
>>> self.env ['res.partner']
+
res.partner
+
>>> self.env ['res.partner']。search([['is_company','=',True],['customer','='
+

2017年1月11日 (三) 09:25的最新版本

记录集(RecordSet)

模型和记录的交互通过记录集(同一模型的一组有序记录)进行。

提示
与名称暗示相反,记录集可能包含重复数据。这可能会在将来更改完善。

在模型上定义的方法在记录集上执行,它们的self是记录集:

Class AModel(models.Model):
    _name ='a.model'
    def a_method(self):
        #self可以在0个记录和所有记录之间的任何地方
        #数据库
        self.do_operation()

在记录集上迭代将产生一组单个记录(“singletons”),很像在Python字符串上迭代产生单个字符的字符串:

def do_operation(self):
    print self            #=> a.model(1,2,3,4,5)
    for record in self:
        print self         #=> a.model(1),然后a.model(2),然后a.model(3),...

字段访问

记录集提供了一个“活动记录”接口:模型字段可以直接从记录中读取和写入,但只能在单例记录集(单记录记录集)上读取和写入。设置字段的值将触发对数据库的更新:

>>> record.name
示例名称  #返回 record 记录 name 字段的值
>>> record.company_id.name
公司名    #返回公司名称
>>> record.name =“Bob”

尝试在多个记录上读取或写入字段将引发错误。 访问关系字段(Many2one,One2many,Many2many)总是返回记录集,如果未设置字段,则为空。

危险
每个对字段的赋值触发数据库更新,在同时设置多个字段或在多个记录上设置字段(使用相同的值)时,请使用write():
#3 * len(records)次数据库更新
for record in records:
    record.a = 1
    record.b = 2
    record.c = 3
#len(records)次数据库更新
for record in records:
    record.write({'a':1,'b':2,'c':3})

#1次数据库更新
records.write({'a':1,'b':2,'c':3})

记录缓存和预取

Odoo为记录的字段维护一个缓存,所以不是每个字段访问都会发出一个数据库请求,这对性能来说是可怕的。以下示例仅对第一条语句查询数据库:

record.name#首次访问从数据库读取值
record.name#second access从缓存获取值

为了避免一次读取一个记录上的一个字段,Odoo根据一些启发式方法预取记录和字段以获得良好的性能。一旦必须在给定记录上读取字段,ORM实际上在较大的记录集上读取该字段,并将返回的值存储在高速缓存中供以后使用。预取的记录集通常是记录从中通过迭代而来的记录集。此外,所有简单存储的字段(boolean, integer, float, char, text, date, datetime, selection, many2one)它们对应于模型表的列,并在同一查询中有效地提取。 考虑下面的示例,其中partners是1000条记录的记录集。没有预取,循环将对数据库进行2000次查询。使用预取,只进行一个查询:

for partner in partners:
    print partner.name          # first pass prefetches 'name' and 'lang'
                                # (and other fields) on all 'partners'
    print partner.lang

预取也对辅助记录起作用:当读取关系字段时,它们的值(它们是记录)被预订用于将来的预取。访问这些辅助记录之一会从同一模型预取所有辅助记录。这使得以下示例只生成两个查询,一个用于合作伙伴,一个用于国家/地区:

countries = set()
for partner in partners:
    country = partner.country_id        # first pass prefetches all partners
    countries.add(country.name)         # first pass prefetches all countries

集合操作

记录集是不可变的,但是可以使用各种集合操作来组合相同模型的集合,返回新的记录集。集合操作不保留顺序。

record in set returns whether record (which must be a 1-element recordset) is present in set. record not in set is the inverse operation
set1 <= set2 and set1 < set2 return whether set1 is a subset of set2 (resp. strict)
set1 >= set2 and set1 > set2 return whether set1 is a superset of set2 (resp. strict)
set1 | set2 returns the union of the two recordsets, a new recordset containing all records present in either source
set1 & set2 returns the intersection of two recordsets, a new recordset containing only records present in both sources
set1 - set2 returns a new recordset containing only records of set1 which are not in set2
 

其他记录集操作

记录集是可迭代的,所以通常的Python工具可用于