[IMP] base: only pass to the webclient the fields it requires
The main goal is to reduce the number of KB sent by the `get_views` method to the web client by getting rid of things not used by the web client. This revision aims to only pass the `fields_get` info of fields actually required by the web client. Before this revision, for each view, the list of all fields of all models implied in the view are passed. For the main view, it's required to pass all the fields, for the search view: The advanced search needs to know all fields of the model to be able to let the user to do advanced filters and groupbys on the model fields. But, for the models of the subviews (one2many/many2many embbeded views), this is not required. Only the fields included in the view are required. Also, if the search view is not requested by the web client, then it's also not required to pass all the fields of the main model. After this revision, for each view, pass the `fields_get` info of only the fields actually implied in the view. For the search view, info of all fields are passed, not only the ones implied in the view. For instance, on the `get_views` of `account.move`, this allows a gain of an extra 18,05KB, reducing from 165.82 to 147.77KB. In addition, before this revision, the whole content of `fields_get` was stored in the cache of `_get_view_cache`, meaning per view. If 3 views were requested on `get_views` let's say kanban, list, form, the same whole `fields_get` info, of all fields, was stored 3 times in the cache. This revision removes the content of fields_get of the cache for `get_views`, to avoid storing multiple times the exact same information in the cache, therefore gaining tremendous memory, while not loosing that processing time. The decrease of speed is only 1~3ms per call to `get_views`. This is mainly because all the information gathered by `fields_get` is already in the cache. For instance, it doesn't require any SQL request (at the moment). e.g. the translations (string, help, selection) are already cached. closes odoo/odoo#99834 Related: odoo/enterprise#31167 Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This commit is contained in:
@@ -11,5 +11,6 @@ class View(models.Model):
|
||||
if node.xpath("ancestor::div[hasclass('oe_chatter')]"):
|
||||
# Pass the postprocessing of the mail thread fields
|
||||
# The web client makes it completely custom, and this is therefore pointless.
|
||||
name_manager.has_field(node, node.get('name'), {})
|
||||
return
|
||||
return super()._postprocess_tag_field(node, name_manager, node_info)
|
||||
|
||||
@@ -1006,14 +1006,14 @@ actual arch.
|
||||
|
||||
arch = etree.tostring(node, encoding="unicode").replace('\t', '')
|
||||
|
||||
models = set()
|
||||
models = {}
|
||||
name_managers = [name_manager]
|
||||
for name_manager in name_managers:
|
||||
models.add(name_manager.model._name)
|
||||
models.setdefault(name_manager.model._name, set()).update(name_manager.available_fields)
|
||||
name_managers.extend(name_manager.children)
|
||||
return arch, models
|
||||
|
||||
def _postprocess_access_rights(self, tree, models):
|
||||
def _postprocess_access_rights(self, tree):
|
||||
"""
|
||||
Apply group restrictions: elements with a 'groups' attribute should
|
||||
be removed from the view to people who are not members.
|
||||
@@ -1022,14 +1022,6 @@ actual arch.
|
||||
views can add additional specific rights like creating columns for
|
||||
many2one-based grouping views.
|
||||
"""
|
||||
models = {
|
||||
model: {
|
||||
fname: field
|
||||
for fname, field in fields.items()
|
||||
if not field.get('groups') or self.user_has_groups(field['groups'])
|
||||
}
|
||||
for model, fields in models.items()
|
||||
}
|
||||
|
||||
for node in tree.xpath('//*[@groups]'):
|
||||
if not self.user_has_groups(node.attrib.pop('groups')):
|
||||
@@ -1073,7 +1065,7 @@ actual arch.
|
||||
not self._context.get(action, True) and is_base_model):
|
||||
node.set(action, 'false')
|
||||
|
||||
return tree, models
|
||||
return tree
|
||||
|
||||
def _postprocess_view(self, node, model_name, editable=True, parent_name_manager=None, **options):
|
||||
""" Process the given architecture, modifying it in-place to add and
|
||||
|
||||
+19
-10
@@ -1654,11 +1654,22 @@ class BaseModel(metaclass=MetaModel):
|
||||
for [v_id, v_type] in views
|
||||
}
|
||||
|
||||
result['models'] = {
|
||||
model: fields
|
||||
for info in result['views'].values()
|
||||
for model, fields in info.pop('models').items()
|
||||
}
|
||||
models = {}
|
||||
for view in result['views'].values():
|
||||
for model, model_fields in view.pop('models').items():
|
||||
models.setdefault(model, {'id', self.CONCURRENCY_CHECK_FIELD}).update(model_fields)
|
||||
|
||||
result['models'] = {}
|
||||
|
||||
if 'search' in result['views']:
|
||||
# If the search view is requested, all fields of the main model must be passed.
|
||||
result['models'][self._name] = self.fields_get(attributes=self._get_view_field_attributes())
|
||||
models.pop(self._name)
|
||||
|
||||
for model, model_fields in models.items():
|
||||
result['models'][model] = self.env[model].fields_get(
|
||||
allfields=model_fields, attributes=self._get_view_field_attributes()
|
||||
)
|
||||
|
||||
# Add related action information if asked
|
||||
if options.get('toolbar'):
|
||||
@@ -1791,10 +1802,8 @@ class BaseModel(metaclass=MetaModel):
|
||||
# TODO: only `web_studio` seems to require this. But this one on the other hand should be eliminated:
|
||||
# you just called `get_views` for that model, so obviously the web client already knows the model.
|
||||
'model': self._name,
|
||||
# sudo is important to get all fields, including fields restricted to groups, in the cache.
|
||||
'models': {model: frozendict(self.env[model].sudo().fields_get(
|
||||
attributes=self._get_view_field_attributes(),
|
||||
)) for model in models},
|
||||
# Set a frozendict and tuple for the field list to make sure the value in cache cannot be updated.
|
||||
'models': frozendict({model: tuple(fields) for model, fields in models.items()}),
|
||||
}
|
||||
|
||||
return frozendict(result)
|
||||
@@ -1824,7 +1833,7 @@ class BaseModel(metaclass=MetaModel):
|
||||
result = dict(self._get_view_cache(view_id, view_type, **options))
|
||||
|
||||
node = etree.fromstring(result['arch'])
|
||||
node, result['models'] = self.env['ir.ui.view']._postprocess_access_rights(node, result['models'])
|
||||
node = self.env['ir.ui.view']._postprocess_access_rights(node)
|
||||
result['arch'] = etree.tostring(node, encoding="unicode").replace('\t', '')
|
||||
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user