[IMP] move application of view inheritance outside of fields_view_get and into View.

change get_root_ancestor to return just the id of the ancestor view

bzr revid: xmo@openerp.com-20130423150844-eubxue9vbtc6jhof
This commit is contained in:
Xavier Morel 2013-04-23 17:08:44 +02:00
parent 8914886040
commit d40ec67c2d
3 changed files with 48 additions and 40 deletions

View File

@ -21,6 +21,7 @@
import copy
import logging
import itertools
from lxml import etree
import os
@ -164,6 +165,35 @@ class view(osv.osv):
if not cr.fetchone():
cr.execute('CREATE INDEX ir_ui_view_model_type_inherit_id ON ir_ui_view (model, inherit_id)')
def read_combined(self, cr, uid, view_id, fields=None, model=None, context=None):
"""
Reads the specified view and returns it after applying all inheriting
views upon it (essentially reads the "currently final" view)
Returns `False` if the provided id is not a valid view, or if `False`
is provided as an id.
The `arch` of the view is always read (regardless of its presence in
`fields`), and is returned as an lxml tree
:param list(str) fields: same as in BaseModel.read()
:param str model:
"""
if fields and 'arch' not in fields:
fields = list(itertools.chain(['arch'], fields))
if not view_id: return False
views = self.read(cr, uid, [view_id], fields=fields, context=context)
if not views: return False
base_arch = views[0]['arch']
base_arch = base_arch.encode('utf-8') if isinstance(base_arch, unicode) else base_arch
return dict(views[0], arch=reduce(
lambda current_arch, descendant: self.apply_inheritance_specs(
cr, uid, model, view_id, current_arch, *descendant, context=context),
self.iter(cr, uid, view_id, model, exclude_base=True, context=context),
etree.fromstring(base_arch)
))
def locate_node(self, arch, spec):
""" Locate a node in a source (parent) architecture.
@ -246,7 +276,7 @@ class view(osv.osv):
`exclude_base` is `False`, the default)
"""
if not exclude_base:
[base] = self.browse(cr, uid, [view_id], context=context)
base = self.browse(cr, uid, view_id, context=context)
yield base.id, base.arch
for arch, id in self.get_inheriting_views_arch(
@ -259,8 +289,8 @@ class view(osv.osv):
def get_root_ancestor(self, cr, uid, view_id=None,
model=None, view_type=None, context=None):
"""
Fetches the root of the view tree specified by the id or (type, model)
parameters.
Fetches the id of the root of the view tree specified by the id or
(type, model) parameters.
If view_id is specified, view_type and model aren't needed (and the
other way around)
@ -268,7 +298,7 @@ class view(osv.osv):
:param view_id: id of view to search the root ancestor of
:param str model: model to use the view for
:param str view_type: expected view type
:return:
:return: id of the root view for the tree
"""
assert view_id or (model and view_type),\
"caller must provide either a view_id or a model and a view_type"\
@ -291,11 +321,7 @@ class view(osv.osv):
while view.inherit_id:
view = view.inherit_id
views = self.read(cr, uid, [view.id],[
'arch', 'name', 'field_parent',
'id', 'type', 'inherit_id', 'model'
], context=context)
return views[0]
return view.id
def raise_view_error(self, cr, uid, model, error_msg, view_id, child_view_id, context=None):

View File

@ -2054,26 +2054,6 @@ class BaseModel(object):
context = {}
View = self.pool['ir.ui.view']
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
def apply_view_inheritance(cr, user, source, inherit_id):
""" Apply all the (directly and indirectly) inheriting views.
:param source: a parent architecture to modify (with parent
modifications already applied)
:param inherit_id: the database view_id of the parent view
:return: a modified source where all the modifying architecture
are applied
"""
return reduce(
lambda s, descendant: View.apply_inheritance_specs(
cr, user, self._name, inherit_id, s, *descendant, context=context),
View.iter(cr, user, inherit_id, self._name, exclude_base=True, context=context),
source)
result = {'type': view_type, 'model': self._name}
view_ref = context.get(view_type + '_view_ref')
@ -2085,12 +2065,14 @@ class BaseModel(object):
if view_ref_res:
view_id = view_ref_res[0]
root_view = View.get_root_ancestor(
root_view_id = View.get_root_ancestor(
cr, user, view_id, self._name, view_type, context=context)
root_view = View.read_combined(cr, user, root_view_id, fields=[
'id', 'name', 'field_parent', 'type', 'model'
], model=self._name, context=context)
if root_view:
source = etree.fromstring(encode(root_view['arch']))
result.update(
arch=apply_view_inheritance(cr, user, source, root_view['id']),
arch=root_view['arch'],
type=root_view['type'],
view_id=root_view['id'],
name=root_view['name'],

View File

@ -163,22 +163,22 @@ class TestViewInheritance(common.TransactionCase):
def test_find_root(self):
A_id = self.ids['A']
root = self.View.get_root_ancestor(self.cr, self.uid, view_id=A_id)
self.assertEqual(root['id'], A_id,
root_id = self.View.get_root_ancestor(self.cr, self.uid, view_id=A_id)
self.assertEqual(root_id, A_id,
"when given a root view, operation should be id")
root = self.View.get_root_ancestor(
root_id = self.View.get_root_ancestor(
self.cr, self.uid, view_id=self.ids['A11'])
self.assertEqual(root['id'], A_id)
self.assertEqual(root_id, A_id)
root = self.View.get_root_ancestor(
root_id = self.View.get_root_ancestor(
self.cr, self.uid, view_id=self.ids['A221'])
self.assertEqual(root['id'], A_id)
self.assertEqual(root_id, A_id)
# search by model
root = self.View.get_root_ancestor(
root_id = self.View.get_root_ancestor(
self.cr, self.uid, model=self.model, view_type='form')
self.assertEqual(root['id'], A_id)
self.assertEqual(root_id, A_id)
def test_no_root(self):
root = self.View.get_root_ancestor(