Odoo12 ORM API ☞ Recordsets

Recordsets(记录集)


8.0版中的新功能: 此页面记录了Odoo 8.0中添加的 NEW API,它应该是未来的主要开发API。Odoo12依旧提供兼容OpenERP 7.0更甚之前中"old API",但此处不再提及"old API",如需请参阅之前API文档。

与模型和记录的交互是通过Recordsets执行的,Recordsets是同一模型的有序记录集。

Warning!
Recordsets,名称中为set,即为无重复记录集,但目前Recordsets(记录集)可能包含重复项。后边可能会有所改变。

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

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()

迭代记录集将得到新的单个记录(“singletons”),就像迭代Python字符串得到单个字符:

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), ...

Field access(字段访问)

Recordsets提供“Active Record” 接口:模型字段可以作为属性直接从记录中读取和写入,但仅限于单例(single-record recordsets)。字段的值就可以像字典一样直接访问,这种方式要比使用字段的*“getattr()”*方法来访问要优雅和安全。当设置字段的值时会触发数据库的更新操作。

>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"
>>> field = "name"
>>> record[field]
Bob

当试图对多记录(multiple records)的进行读取或者写入操作时会报错!
访问一个关系字段(如Many2one,One2many,Many2many)会始终返回记录集,如果未设置字段,则为空。

Danger!
对字段的每个赋值都会触发数据库更新,在同时设置多个字段或在多个记录上设置字段(相同的值)时,请使用write():

# 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})

Record cache and prefetching(记录缓存和预取)

Odoo会为记录字段维护一个缓存,这样就不需要访问每个字段都发出数据库请求,如果每取一个字段就去数据库查询一次,性能就会变的很糟糕。示例中仅针对第一个语句查询数据库,第二次会从缓存中取值:

record.name             # first access reads value from database
record.name             # second access gets value from cache

为了避免一次读取一条记录上一个字段,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

Set operations(集合操作)

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

  • record in set 返回 record 是否存在于 set 中。record not in set 即判断是否不在 set 中。
  • set1 <= set2set1 < set2 返回 set1 是否是 set2 的一个子集(或严格是一个子集)。
  • set1 >= set2set1 > set2 返回 set1 是否是 set2 的一个父(超)集(或严格是一个父集)。
  • set1 | set2 返回两个recordsets的并集,包含任一 set 中都存在的所有记录的新记录集。
  • set1 & set2 返回两个recordsets的交集,包含两个 set 中都存在的所有记录的新记录集。
  • set1 - set2 返回仅包含 set1 的记录的新记录集,这些记录不存在于 set2 中。

Other recordset operations(其他集合操作)

Recordsets 是可迭代的,因此通常的Python工具可用于转换(map(),sorted(),itertools.ifilter,…)但是这些工具返回 listiterator, 去掉了在返回结果上调用方法或使用集合操作的能力。
因此,Recordsets 提供这些操作返回recordsets (记录集)本身的操作方法(如果可能):

filtered()
返回仅包含满足提供的条件函数的记录的记录集。条件也可以是一个字符串按字段为true或false进行过滤:

# 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()
返回按提供的key函数排序的记录集。如果未提供key,将使用模型的默认排序顺序:

# sort records by name
records.sorted(key=lambda r: r.name)

mapped()
将提供的函数应用于Recordset中的每个record(记录),如果结果是Recordset,则返回Recordset:

# returns a list of summing two fields for each record in the set
records.mapped(lambda r: r.field1 + r.field2)

提供的函数可以是获取字段值的字符串:

# returns a list of names
records.mapped('name')

# returns a recordset of partners
record.mapped('partner_id')

# returns the union of all partner banks, with duplicates removed
record.mapped('partner_id.bank_ids')

猜你喜欢

转载自blog.csdn.net/sinat_23931991/article/details/84975863