The relationship between odoo12 record and model one

When you want to do batch update data. A problem was found. direct 

self.env[''].write({}) is invalid. . Query data found:

model.create() records.write(). . In this case. As a developer. I must figure out this relationship

1. Find out where the model is

Because odoo loads the model dynamically. So first find out what type of current model is

Just find a model. Operable place 

print(self.__class__) 

<class'odoo.api.zhy.sale'>. . As can be seen. All are dynamically loaded into the odoo.api module

Second, how to distinguish between record and model

Debugging can be seen

Then for order in self:

. . As can be seen. It must have rewritten some magic functions of the model

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

As can be seen. The _ids attribute is the key to record and model

 

3. What the hell is 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)

First, the cls.envs global variable saves all env

Then rewrite []. self.env[''] is equivalent to getting the registered model and then _browse an empty record() ( empty reocord can be understood as mode l, which initializes some other parameters)

So self.env[''] gets an empty record(model)

self.registry[model_name] is the model without _browse

Four, what is _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

As can be seen. Is to generate a model, and then assign the passed id

The advantage of this is that the real record will only be generated when traversing (determining the need for record). To use. The others are represented by a record(_ids). Reduce a lot of memory space

Specifically how to write ids. Please see the second analysis

5. Why doesn't self.env[''].write(()) take effect

Include self.env[""] which is model. Why does wirte not take effect

Look at the write code

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

You can see it here. The model must have rewritten the _bool_ magic function,

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

can be seen. The true and flase of model are determined based on _ids.

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

_ids=()

So the _ids attribute of self.env[""] is {}.

Can't batch wirte

Guess you like

Origin blog.csdn.net/sr50611/article/details/100096401