万恶之源:
@api.depends("girls", "boys")
def _compute_boys_per(self):
for record in self:
record.per = record.boys/(record.boys + record.girls)
这是一段典型的odoo的代码,作为初学者,我看了只有有点懵,在for循环内部对self和record做了print操作,发现居然是一样的,瞬间傻了。接下来的内容中,简单的说下。
class BaseModel:
def __iter__(self):
""" Return an iterator over ``self``. """
for id in self._ids:
yield self._browse((id,), self.env, self._prefetch)
#
# Instance creation
# 创建实例
#
# An instance represents an ordered collection of records in a given
# execution environment. The instance object refers to the environment, and
# the records themselves are represented by their cache dictionary. The 'id'
# of each record is found in its corresponding cache dictionary.
# 创建一个给定执行环境中记录的有序集合的实例。实例对象提供了环境,并且记录
# 本身由缓存字典表示。每一个记录的id都在相应的缓存字典中找到
#
# This design has the following advantages:
# - cache access is direct and thus fast;
# - one can consider records without an 'id' (see new records);
# - the global cache is only an index to "resolve" a record 'id'.
#
@classmethod
def _browse(cls, ids, env, prefetch=None):
""" Create a recordset instance.
:param ids: a tuple of record ids
:param env: an environment
:param prefetch: an optional prefetch object
"""
records = object.__new__(cls)
records.env = env
records._ids = ids
if prefetch is None:
prefetch = defaultdict(set) # {model_name: set(ids)}
records._prefetch = prefetch
prefetch[cls._name].update(ids)
def browse(self, arg=None, prefetch=None):
""" browse([ids]) -> records
Returns a recordset for the ids provided as parameter in the current
environment.
Can take no ids, a single id or a sequence of ids.
这个就是格式化ids的结构
"""
ids = _normalize_ids(arg)
#assert all(isinstance(id, IdType) for id in ids), "Browsing invalid ids: %s" % ids
return self._browse(ids, self.env, prefetch)
@api.returns('self')
def exists(self):
""" exists() -> records
Returns the subset of records in ``self`` that exist, and marks deleted
records as such in cache. It can be used as a test on records::
返回self中存在的记录的子集,并且标记缓存中删除的记录。他可以用来在记录上做测试。
if record.exists():
...
By convention, new records are returned as existing.
"""
ids, new_ids = [], []
for i in self._ids:
(ids if isinstance(i, pycompat.integer_types) else new_ids).append(i)
if not ids:
return self
query = """SELECT id FROM "%s" WHERE id IN %%s""" % self._table
self._cr.execute(query, [tuple(ids)])
ids = [r[0] for r in self._cr.fetchall()]
existing = self.browse(ids + new_ids)
if len(existing) < len(self):
# mark missing records in cache with a failed value
exc = MissingError(_("Record does not exist or has been deleted."))
self.env.cache.set_failed(self - existing, self._fields.values(), exc)
return existing
以上来自odoo/models.py
我们从下往上看
从数据库中拿到记录相关的ids
_browse创建了一个实例
__iter__用的是yield格式,每次从ids中拿出一个id,通过_browse生成这条记录的一个实例。
如果对__iter__迭代器这块有不理解请看: