In this viewtiverse, the heroes remove the context dependencies for `get_views`, from the views and python fields (such as domain). To reduce inconsistencies and the number of rpc. Current issues: * There may be inconsistencies in views at the JavaScript level. Some overrides modify the behavior of get_views or domains on fields via context keys, therefore by changing the action, the rendering may be different. However, these views are cached. However, the cache key (Javascript) does not reflect the entire context, and requires additional post-processing from the server. * Multiple rpc for the same rendering. get_views being dependent on the context, as soon as it changes, a new rpc is performed. In most cases, when JavaScript needs the same view, there is no change depending on the context, the rpc is useless. * Inconsistency when rendering subviews, some views could be different depending on the context, this context can be modified in the view itself via the context attributes. However, the JavaScript client does not redo an rpc for each change of these sub-contexts. Therefore the result may be inconsistent. Solution: Limit as much as possible the number of context keys provided when calling get_views, and use the context provided as a cache key. The authorized keys are 'lang' and '*_view_ref'. For the cache key, options are added in the get_views method. Instead of using the context, it is inserted into python expressions. This will be evaluated by JavaScript and thus avoids inconsistencies. task-3414108 task-3414068 closes odoo/odoo#135145 Related: odoo/enterprise#47584 Signed-off-by: Raphael Collet <rco@odoo.com>
76 lines
3.1 KiB
Python
76 lines
3.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import odoo
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class BaseModuleUpgrade(models.TransientModel):
|
|
_name = "base.module.upgrade"
|
|
_description = "Upgrade Module"
|
|
|
|
@api.model
|
|
@api.returns('ir.module.module')
|
|
def get_module_list(self):
|
|
states = ['to upgrade', 'to remove', 'to install']
|
|
return self.env['ir.module.module'].search([('state', 'in', states)])
|
|
|
|
@api.model
|
|
def _default_module_info(self):
|
|
return "\n".join("%s: %s" % (mod.name, mod.state) for mod in self.get_module_list())
|
|
|
|
module_info = fields.Text('Apps to Update', readonly=True, default=_default_module_info)
|
|
|
|
@api.model
|
|
def get_view(self, view_id=None, view_type='form', **options):
|
|
res = super().get_view(view_id, view_type, **options)
|
|
if view_type != 'form':
|
|
return res
|
|
|
|
if not self.get_module_list():
|
|
res['arch'] = '''<form string="Upgrade Completed">
|
|
<separator string="Upgrade Completed" colspan="4"/>
|
|
<footer>
|
|
<button name="config" string="Start Configuration" type="object" class="btn-primary" data-hotkey="q"/>
|
|
<button special="cancel" data-hotkey="x" string="Close" class="btn-secondary"/>
|
|
</footer>
|
|
</form>'''
|
|
|
|
return res
|
|
|
|
def upgrade_module_cancel(self):
|
|
Module = self.env['ir.module.module']
|
|
to_install = Module.search([('state', 'in', ['to upgrade', 'to remove'])])
|
|
to_install.write({'state': 'installed'})
|
|
to_uninstall = Module.search([('state', '=', 'to install')])
|
|
to_uninstall.write({'state': 'uninstalled'})
|
|
return {'type': 'ir.actions.act_window_close'}
|
|
|
|
def upgrade_module(self):
|
|
Module = self.env['ir.module.module']
|
|
|
|
# install/upgrade: double-check preconditions
|
|
mods = Module.search([('state', 'in', ['to upgrade', 'to install'])])
|
|
if mods:
|
|
query = """ SELECT d.name
|
|
FROM ir_module_module m
|
|
JOIN ir_module_module_dependency d ON (m.id = d.module_id)
|
|
LEFT JOIN ir_module_module m2 ON (d.name = m2.name)
|
|
WHERE m.id in %s and (m2.state IS NULL or m2.state IN %s) """
|
|
self._cr.execute(query, (tuple(mods.ids), ('uninstalled',)))
|
|
unmet_packages = [row[0] for row in self._cr.fetchall()]
|
|
if unmet_packages:
|
|
raise UserError(_('The following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages)))
|
|
|
|
# terminate transaction before re-creating cursor below
|
|
self._cr.commit()
|
|
odoo.modules.registry.Registry.new(self._cr.dbname, update_module=True)
|
|
self._cr.reset()
|
|
|
|
return {'type': 'ir.actions.act_window_close'}
|
|
|
|
def config(self):
|
|
# pylint: disable=next-method-called
|
|
return self.env['res.config'].next()
|