[IMP] web: allow lazy-loading asset bundles' templates

Previously, lazy-loading xml templates was only possible by fetching the
xml file directly, this meant that it was impossible to lazy-load an
entire bundle's templates with a single request. Additionally,
requesting the xml files directly meant that no inheritance was applied,
causing the need for a separate inheritance system using t-jquery on the
client-side.

This commit alters the /web/webclient/qweb route so that it now takes a
bundle id, meaning that it is now possible to lazy-load the xml from
arbitrary bundles.

task-2497943

closes odoo/odoo#70084

Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
This commit is contained in:
Samuel Degueldre
2021-05-03 07:25:20 +00:00
parent 830a28b6ad
commit 557a24e4f4
4 changed files with 15 additions and 13 deletions
+10 -10
View File
@@ -549,13 +549,13 @@ class HomeStaticTemplateHelpers(object):
return etree.tostring(root, encoding='utf-8') if root is not None else b'', checksum.hexdigest()[:64]
def _get_asset_paths(self):
def _get_asset_paths(self, bundle):
"""Proxy for ir_asset._get_asset_paths
Useful to make 'self' testable.
"""
return request.env['ir.asset']._get_asset_paths(addons=self.addons, bundle='web.assets_qweb', xml=True)
return request.env['ir.asset']._get_asset_paths(addons=self.addons, bundle=bundle, xml=True)
def _get_qweb_templates(self):
def _get_qweb_templates(self, bundle):
"""One and only entry point that gets and evaluates static qweb templates
:rtype: (str, str)
@@ -563,7 +563,7 @@ class HomeStaticTemplateHelpers(object):
xml_paths = defaultdict(list)
# group paths by module, keeping them in order
for path, addon, _ in self._get_asset_paths():
for path, addon, _ in self._get_asset_paths(bundle):
addon_paths = xml_paths[addon]
if path not in addon_paths:
addon_paths.append(path)
@@ -572,12 +572,12 @@ class HomeStaticTemplateHelpers(object):
return content, checksum
@classmethod
def get_qweb_templates_checksum(cls, addons=None, db=None, debug=False):
return cls(addons, db, checksum_only=True, debug=debug)._get_qweb_templates()[1]
def get_qweb_templates_checksum(cls, addons=None, db=None, debug=False, bundle=None):
return cls(addons, db, checksum_only=True, debug=debug)._get_qweb_templates(bundle)[1]
@classmethod
def get_qweb_templates(cls, addons=None, db=None, debug=False):
return cls(addons, db, debug=debug)._get_qweb_templates()[0]
def get_qweb_templates(cls, addons=None, db=None, debug=False, bundle=None):
return cls(addons, db, debug=debug)._get_qweb_templates(bundle)[0]
class GroupsTreeNode:
@@ -934,12 +934,12 @@ class WebClient(http.Controller):
])
@http.route('/web/webclient/qweb/<string:unique>', type='http', auth="none", cors="*")
def qweb(self, unique, mods=None, db=None):
def qweb(self, unique, mods=None, db=None, bundle=None):
if not request.db and mods is None:
mods = odoo.conf.server_wide_modules or []
content = HomeStaticTemplateHelpers.get_qweb_templates(mods, db, debug=request.session.debug)
content = HomeStaticTemplateHelpers.get_qweb_templates(mods, db, debug=request.session.debug, bundle=bundle)
return request.make_response(content, [
('Content-Type', 'text/xml'),
+1 -1
View File
@@ -51,7 +51,7 @@ class Http(models.AbstractModel):
mods = odoo.conf.server_wide_modules or []
if request.db:
mods = list(request.registry._init_modules) + mods
qweb_checksum = HomeStaticTemplateHelpers.get_qweb_templates_checksum(debug=request.session.debug)
qweb_checksum = HomeStaticTemplateHelpers.get_qweb_templates_checksum(debug=request.session.debug, bundle="web.assets_qweb")
lang = user_context.get("lang")
translation_hash = request.env['ir.translation'].get_web_translations_hash(mods, lang)
menu_json_utf8 = json.dumps(request.env['ir.ui.menu'].load_menus(request.session.debug), default=ustr, sort_keys=True).encode()
+1 -1
View File
@@ -225,7 +225,7 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
var lock = this.qweb_mutex.exec(function () {
var cacheId = self.cache_hashes && self.cache_hashes.qweb;
var route = '/web/webclient/qweb/' + (cacheId ? cacheId : Date.now());
return $.get(route).then(function (doc) {
return $.get(route, { bundle: 'web.assets_qweb' }).then(function (doc) {
if (!doc) { return; }
const owlTemplates = [];
for (let child of doc.querySelectorAll("templates > [owl]")) {
+3 -1
View File
@@ -1293,7 +1293,9 @@ python implementation.
Now, let us explain how the templates are loaded. Whenever the web client
starts, a rpc is made to the */web/webclient/qweb* route. The server will then
return a list of all templates defined in data files for each installed modules.
The correct files are listed in the *qweb* entry in each module manifest.
The correct files are listed in the *web.assets_qweb* entry in each module
manifest. It is also possible to lazy-load another bundle's templates by calling
this same route and giving it the corresponding "bundle" query parameter.
The web client will wait for that list of template to be loaded, before starting
its first widget.