odoo12 record 和 model 的关系 一

在想做批量更新数据的时候。发现了个问题。直接 

self.env[''].write({}) 是不生效的。。查询资料发现:

model.create()  records.write()。。这样的话。作为开发人员。肯定要搞清这个关系

一、搞清model在哪

由于 odoo 是动态加载model的。所以要先搞清 当前的model 是 什么类型

随便找个 model。可以操作的地方 

print(self.__class__) 

<class 'odoo.api.zhy.sale'>  。。可以看出。所有是被动态加载到 odoo.api 模块里面了

二、record 和model 如何区分

调试可以看出

然后for order in self:

。。可以看出。肯定重写了 model的一些魔法函数

def __str__(self):
    return "%s%s" % (self._name, getattr(self, '_ids', ""))

可以看出。_ids 属性 是 影响 为record 和model 的关键了

三、self.env["**"] 什么鬼

class Environment(Mapping):
  class Environment(Mapping):
     def __new__(cls, cr, uid, context):
        assert context is not None
        args = (cr, uid, context)

        # if env already exists, return it 这句就是全局envs
        env, envs = None, cls.envs
        for env in envs:
            if env.args == args:
                return env

        # otherwise create environment, and add it in the set
        self = object.__new__(cls)
        self.cr, self.uid, self.context = self.args = (cr, uid, frozendict(context))
        self.registry = Registry(cr.dbname)
        self.cache = envs.cache
        self._cache_key = (cr, uid)
        self._protected = StackMap()                # {field: ids, ...}
        self.dirty = defaultdict(set)               # {record: set(field_name), ...}
        self.all = envs
        envs.add(self)
        return self

    def __getitem__(self, model_name):
        """ Return an empty recordset from the given model. """
        return self.registry[model_name]._browse((), self)

首先 cls.envs 全局变量保存 了所有的 env

然后重写了 [] 。self.env['']  相当于 获取注册的model 然后 _browse 一个空的record() (空的reocord 可以理解为model,里面初始化一些其他参数了)

所以self.env[''] 就是获取了一个 空的record(model)

self.registry[model_name] 为 没 _browse 的model

四、_browse 是什么

    @classmethod
    def _browse(cls, ids, env, prefetch=None, add_prefetch=True):
        """ 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
        if add_prefetch:
            prefetch[cls._name].update(ids)
        return records

可以看出。就是生成一个model,然后把传入的id给赋值上

这样的好处是: 只有遍历的时候(确定需要record)的时候才会生成真正的record。来使用。其他都是一个record(_ids)来表示。减少很大的内存空间了

具体如何写入ids 的。请看二做的分析

五、self.env[''].write({}) 为什么不生效

计入 self.env[""] 也就是model。为什么wirte 不能生效

看下 write 代码

@api.multi
def write(self, vals):
# 所以这里只能是记录
if not self:
    return True

这里可以看到。model 肯定重写了_bool_魔法函数,

def __bool__(self):
    """ Test whether ``self`` is nonempty. """
    return bool(getattr(self, '_ids', True))

可以看到。model 的 true和flase 是根据 _ids决定的。

self.registry[model_name]._browse((), self)

_ids=()

所以 self.env[""] 的_ids属性是 {}。

无法批量wirte的

猜你喜欢

转载自blog.csdn.net/sr50611/article/details/100096401
今日推荐