odoo's loading process three, postprocess processing (XML --- "MODEL) function

Continued from the previous article

Look at the code first

    @api.model
    def postprocess(self, model, node, view_id, in_tree_view, model_fields):
        """Return the description of the fields in the node.

        In a normal call to this method, node is a complete view architecture
        but it is actually possible to give some sub-node (this is used so
        that the method can call itself recursively).

        Originally, the field descriptions are drawn from the node itself.
        But there is now some code calling fields_get() in order to merge some
        of those information in the architecture.

        """
        result = False
        fields = {}
        children = True

        modifiers = {}
        if model not in self.env:
            self.raise_view_error(_('Model not found: %(model)s') % dict(model=model), view_id)
        Model = self.env[model]

        if node.tag in ('field', 'node', 'arrow'):
            if node.get('object'):
                attrs = {}
                views = {}
                xml_form = E.form(*(f for f in node if f.tag == 'field'))
                xarch, xfields = self.with_context(base_model_name=model).postprocess_and_fields(node.get('object'), xml_form, view_id)
                views['form'] = {
                    'arch': xarch,
                    'fields': xfields,
                }
                attrs = {'views': views}
                fields = xfields
            if node.get('name'):
                attrs = {}
                field = Model._fields.get(node.get('name'))
                if field:
                    editable = self.env.context.get('view_is_editable', True) and self._field_is_editable(field, node)
                    children = False
                    views = {}
                    for f in node:
                        if f.tag in ('form', 'tree', 'graph', 'kanban', 'calendar'):
                            node.remove(f)
                            xarch, xfields = self.with_context(
                                base_model_name=model,
                                view_is_editable=editable,
                            ).postprocess_and_fields(field.comodel_name, f, view_id)
                            views[str(f.tag)] = {
                                'arch': xarch,
                                'fields': xfields,
                            }
                    attrs = {'views': views}
                    if field.comodel_name in self.env and field.type in ('many2one', 'many2many'):
                        Comodel = self.env[field.comodel_name]
                        node.set('can_create', 'true' if Comodel.check_access_rights('create', raise_exception=False) else 'false')
                        node.set('can_write', 'true' if Comodel.check_access_rights('write', raise_exception=False) else 'false')
                fields[node.get('name')] = attrs

                field = model_fields.get(node.get('name'))
                if field:
                    orm.transfer_field_to_modifiers(field, modifiers)

        elif node.tag in ('form', 'tree'):
            result = Model.view_header_get(False, node.tag)
            if result:
                node.set('string', result)
            in_tree_view = node.tag == 'tree'

        elif node.tag == 'calendar':
            for additional_field in ('date_start', 'date_delay', 'date_stop', 'color', 'all_day'):
                if node.get(additional_field):
                    fields[node.get(additional_field).split('.', 1)[0]] = {}
            for f in node:
                if f.tag == 'filter':
                    fields[f.get('name')] = {}

        if not self._apply_group(model, node, modifiers, fields):
            # node must be removed, no need to proceed further with its children
            return fields

        # The view architeture overrides the python model.
        # Get the attrs before they are (possibly) deleted by check_group below
        orm.transfer_node_to_modifiers(node, modifiers, self._context, in_tree_view)

        for f in node:
            if children or (node.tag == 'field' and f.tag in ('filter', 'separator')):
                fields.update(self.postprocess(model, f, view_id, in_tree_view, model_fields))

        orm.transfer_modifiers_to_node(modifiers, node)
        return fields

The comment is very clear, according to the xml return Return the description of the fields in the node.

The key function is processed by recursive postprocess_and_fields. The flow inside seems like the previous one. I won't analyze it

Look at the reloadable

How are some attributes in xml, attr state and other attributes handled?

The key function transfer_node_to_modifiers

def transfer_node_to_modifiers(node, modifiers, context=None, in_tree_view=False):
    if node.get('attrs'):
        modifiers.update(safe_eval(node.get('attrs')))

    if node.get('states'):
        if 'invisible' in modifiers and isinstance(modifiers['invisible'], list):
            # TODO combine with AND or OR, use implicit AND for now.
            modifiers['invisible'].append(('state', 'not in', node.get('states').split(',')))
        else:
            modifiers['invisible'] = [('state', 'not in', node.get('states').split(','))]

    for a in ('invisible', 'readonly', 'required'):
        if node.get(a):
            v = bool(safe_eval(node.get(a), {'context': context or {}}))
            if in_tree_view and a == 'invisible':
                # Invisible in a tree view has a specific meaning, make it a
                # new key in the modifiers attribute.
                modifiers['column_invisible'] = v
            elif v or (a not in modifiers or not isinstance(modifiers[a], list)):
                # Don't set the attribute to False if a dynamic value was
                # provided (i.e. a domain from attrs or states).
                modifiers[a] = v

You can see that the attributes are processed here.

Therefore, a lot of code on the Internet is also rewritten through the transfer_node_to_modifiers function to put the uid into attrs. . (I'll write this when I have time, (eval))

Return after processing

def transfer_modifiers_to_node(modifiers, node):
    if modifiers:
        simplify_modifiers(modifiers)
        node.set('modifiers', json.dumps(modifiers))

Go in for json

These two functions will be useful. do not forget.

Send a loadview arch

 <field name="pr_unit" string="&#21333;&#20215;" attrs="{&quot;invisible&quot;: [(&quot;active&quot;, &quot;=&quot;, False)]}" on_change="1" modifiers="{&quot;invisible&quot;: [[&quot;active&quot;, &quot;=&quot;, false]]}"/>\n                           
 <field name="product_uom_qty" string="&#25968;&#37327;" attrs="{&quot;invisible&quot;: [(&quot;active&quot;, &quot;=&quot;, False)]}" on_change="1" modifiers="{&quot;invisible&quot;: [[&quot;active&quot;, &quot;=&quot;, false]], &quot;required&quot;: true}"/>\n                          
  <field name="price_subtotal" string="&#24635;&#39069;" attrs="{&quot;invisible&quot;: [(&quot;active&quot;, &quot;=&quot;, False)]}" modifiers="{&quot;readonly&quot;: true, &quot;invisible&quot;: [[&quot;active&quot;, &quot;=&quot;, false]]}"]]}"/>

return 

You can see that the attrs attributes are all in the modifier. Return to the front-end template for processing

 

Guess you like

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