summaryrefslogtreecommitdiff
path: root/addons/website/models
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-01-09 15:44:05 +0000
committerChristophe Simonis <chs@odoo.com>2019-01-09 15:56:53 +0000
commit8aa8548d8ab68feb13f3bde51c557db84877e809 (patch)
tree930790c1c84a4412db777986f6b2077808560d95 /addons/website/models
parent55a48e341580a6a400c36b6ba0d7b12ff9997f12 (diff)
parent3e4138deaa23b3631dc3fce33cd6d1b3be28ffbd (diff)
[MERGE] forward port branch 12.0 up to 3e4138deaa2
closes odoo/odoo#30045
Diffstat (limited to 'addons/website/models')
-rw-r--r--addons/website/models/ir_http.py4
-rw-r--r--addons/website/models/ir_ui_view.py74
-rw-r--r--addons/website/models/website.py42
3 files changed, 69 insertions, 51 deletions
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 25becf9749c..a649a9acc81 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -74,7 +74,9 @@ class Http(models.AbstractModel):
# Force website with query string paramater, typically set from website selector in frontend navbar
force_website_id = request.httprequest.args.get('fw')
- if force_website_id and request.session.get('force_website_id') != force_website_id:
+ if (force_website_id and request.session.get('force_website_id') != force_website_id and
+ request.env.user.has_group('website.group_multi_website') and
+ request.env.user.has_group('website.group_website_publisher')):
request.env['website']._force_website(request.httprequest.args.get('fw'))
context = {}
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index f45f602fa8b..1a98713326d 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -125,64 +125,50 @@ class View(models.Model):
# get_related_views can be called through website=False routes
# (e.g. /web_editor/get_assets_editor_resources), so website
# dispatch_parameters may not be added. Manually set
- # website_id.
+ # website_id. (It will then always fallback on a website, this
+ # method should never be called in a generic context, even for
+ # tests)
self = self.with_context(website_id=self.env['website'].get_current_website().id)
- views = super(View, self).get_related_views(key, bundles=bundles)
+ return super(View, self).get_related_views(key, bundles=bundles)
+
+ def filter_duplicate(self):
+ """ Filter current recordset only keeping the most suitable view per distinct key.
+ Every non-accessible view will be removed from the set:
+ * In non website context, every view with a website will be removed
+ * In a website context, every view from another website
+ """
current_website_id = self._context.get('website_id')
most_specific_views = self.env['ir.ui.view']
-
if not current_website_id:
- return views
+ return self.filtered(lambda view: not view.website_id)
- for view in views:
+ for view in self:
if view.website_id and view.website_id.id == current_website_id:
most_specific_views |= view
- elif not view.website_id and not any(view.key == view2.key and view2.website_id and view2.website_id.id == current_website_id for view2 in views):
+ elif not view.website_id and not any(view.key == view2.key and view2.website_id and view2.website_id.id == current_website_id for view2 in self):
most_specific_views |= view
return most_specific_views
- @api.multi
- def _sort_suitability_key(self):
- """ Key function to sort views by descending suitability
- Suitability of a view is defined as follow:
- * if the view and request website_id are matched
- * then if the view has no set website
- """
- self.ensure_one()
- context_website_id = self.env.context.get('website_id', 1)
- website_id = self.website_id.id or 0
- different_website = context_website_id != website_id
- return (different_website, website_id)
-
- def filter_duplicate(self):
- """ Filter current recordset only keeping the most suitable view per distinct key """
- view_with_key = self.filtered('key')
- view_without_key = self - view_with_key
- filtered = self.env['ir.ui.view']
- for dummy, group in groupby(view_with_key.sorted('key'), key=lambda record: record.key):
- filtered += sorted(group, key=lambda record: record._sort_suitability_key())[0]
- return (filtered + view_without_key).sorted(key=lambda view: (view.priority, view.id))
+ @api.model
+ def _view_get_inherited_children(self, view, options):
+ extensions = super(View, self)._view_get_inherited_children(view, options)
+ return extensions.filter_duplicate()
@api.model
def _view_obj(self, view_id):
- if isinstance(view_id, str):
- if 'website_id' in self._context:
- domain = [('key', '=', view_id)] + self.env['website'].website_domain(self._context.get('website_id'))
- order = 'website_id'
- else:
- domain = [('key', '=', view_id)]
- order = self._order
- views = self.search(domain, order=order)
- if views:
- return views.filter_duplicate()
- else:
- return self.env.ref(view_id)
- elif isinstance(view_id, int):
- return self.browse(view_id)
-
- # assume it's already a view object (WTF?)
- return view_id
+ ''' Given an xml_id or a view_id, return the corresponding view record.
+ In case of website context, return the most specific one.
+ :param view_id: either a string xml_id or an integer view_id
+ :return: The view record or empty recordset
+ '''
+ if isinstance(view_id, str) or isinstance(view_id, int):
+ return self.env['website'].viewref(view_id)
+ else:
+ # It can already be a view object when called by '_views_get()' that is calling '_view_obj'
+ # for it's inherit_children_ids, passing them directly as object record. (Note that it might
+ # be a view_id from another website but it will be filtered in 'get_related_views()')
+ return view_id if view_id._name == 'ir.ui.view' else self.env['ir.ui.view']
@api.model
def _get_inheriting_views_arch_website(self, view_id):
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 0a99b8ef8eb..82709c4663d 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -173,7 +173,6 @@ class Website(models.Model):
default_menu = self.env.ref('website.main_menu')
self.copy_menu_hierarchy(default_menu)
- @api.model
def copy_menu_hierarchy(self, top_menu):
def copy_menu(menu, t_menu):
new_menu = menu.copy({
@@ -281,11 +280,6 @@ class Website(models.Model):
key_copy = string + (inc and "-%s" % inc or "")
return key_copy
- def key_to_view_id(self, view_id):
- return self.env['ir.ui.view'].search([
- ('id', '=', view_id), ('type', '=', 'qweb')
- ] + self.env['website'].website_domain(self._context.get('website_id')))
-
@api.model
def page_search_dependencies(self, page_id=False):
""" Search dependencies just for information. It will not catch 100%
@@ -506,6 +500,42 @@ class Website(models.Model):
return request.env.user.id == request.website.user_id.id
@api.model
+ def viewref(self, view_id, raise_if_not_found=True):
+ ''' Given an xml_id or a view_id, return the corresponding view record.
+ In case of website context, return the most specific one.
+ :param view_id: either a string xml_id or an integer view_id
+ :param raise_if_not_found: should the method raise an error if no view found
+ :return: The view record or empty recordset
+ '''
+ View = self.env['ir.ui.view']
+ view = None
+ if isinstance(view_id, str):
+ if 'website_id' in self._context:
+ domain = [('key', '=', view_id)] + self.env['website'].website_domain(self._context.get('website_id'))
+ order = 'website_id'
+ else:
+ domain = [('key', '=', view_id)]
+ order = View._order
+ views = View.with_context(active_test=False).search(domain, order=order)
+ if views:
+ view = views.filter_duplicate()
+ else:
+ view = self.env.ref(view_id)
+ # self.env.ref might return something else than an ir.ui.view (eg: a theme.ir.ui.view)
+ if view._name != 'ir.ui.view':
+ view = None
+ elif isinstance(view_id, int):
+ view = View.browse(view_id)
+ else:
+ raise ValueError('Expecting a string or an integer, not a %s.' % (type(view_id)))
+
+ if view:
+ return view
+ if raise_if_not_found:
+ raise ValueError('No record found for unique ID %s. It may have been deleted.' % (view_id))
+ return None
+
+ @api.model
def get_template(self, template):
View = self.env['ir.ui.view']
if isinstance(template, int):