[MERGE] upstream
bzr revid: fme@openerp.com-20140120161129-elnp1afn8ognyc6z
This commit is contained in:
commit
05e2942121
|
@ -18,7 +18,6 @@
|
||||||
<field name="street">1725 Slough Ave.</field>
|
<field name="street">1725 Slough Ave.</field>
|
||||||
<field name="city">Scranton</field>
|
<field name="city">Scranton</field>
|
||||||
<field name="zip">18540</field>
|
<field name="zip">18540</field>
|
||||||
<field name="country_id" ref="us"/>
|
|
||||||
<field name="phone">+1 555 123 8069</field>
|
<field name="phone">+1 555 123 8069</field>
|
||||||
<field name="email">info@yourcompany.example.com</field>
|
<field name="email">info@yourcompany.example.com</field>
|
||||||
<field name="website">www.example.com</field>
|
<field name="website">www.example.com</field>
|
||||||
|
|
|
@ -99,7 +99,7 @@ class ir_http(osv.AbstractModel):
|
||||||
|
|
||||||
# check authentication level
|
# check authentication level
|
||||||
try:
|
try:
|
||||||
auth_method = self._authenticate(getattr(func, "auth", None))
|
auth_method = self._authenticate(func.routing["auth"])
|
||||||
except Exception:
|
except Exception:
|
||||||
# force a Forbidden exception with the original traceback
|
# force a Forbidden exception with the original traceback
|
||||||
return self._handle_exception(
|
return self._handle_exception(
|
||||||
|
|
|
@ -20,6 +20,9 @@ from openerp.tools.translate import _
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# QWeb template engine
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
|
||||||
class QWebException(Exception):
|
class QWebException(Exception):
|
||||||
def __init__(self, message, template=None, node=None, attribute=None):
|
def __init__(self, message, template=None, node=None, attribute=None):
|
||||||
|
@ -28,7 +31,6 @@ class QWebException(Exception):
|
||||||
self.node = node
|
self.node = node
|
||||||
self.attribute = attribute
|
self.attribute = attribute
|
||||||
|
|
||||||
|
|
||||||
class QWebContext(dict):
|
class QWebContext(dict):
|
||||||
def __init__(self, cr, uid, data, loader=None, templates=None, context=None):
|
def __init__(self, cr, uid, data, loader=None, templates=None, context=None):
|
||||||
self.cr = cr
|
self.cr = cr
|
||||||
|
@ -59,29 +61,30 @@ class QWebContext(dict):
|
||||||
class QWeb(orm.AbstractModel):
|
class QWeb(orm.AbstractModel):
|
||||||
"""QWeb Xml templating engine
|
"""QWeb Xml templating engine
|
||||||
|
|
||||||
The templating engine use a very simple syntax, "magic" xml attributes, to
|
The templating engine use a very simple syntax based "magic" xml
|
||||||
produce any kind of texutal output (even non-xml).
|
attributes, to produce textual output (even non-xml).
|
||||||
|
|
||||||
QWebXml:
|
The core magic attributes are:
|
||||||
the template engine core implements the basic magic attributes:
|
|
||||||
|
|
||||||
t-att t-raw t-esc t-if t-foreach t-set t-call t-trim
|
flow attributes:
|
||||||
|
t-if t-foreach t-call
|
||||||
|
|
||||||
|
output attributes:
|
||||||
|
t-att t-raw t-esc t-trim
|
||||||
|
|
||||||
- loader: function that return a template
|
assignation attribute:
|
||||||
|
t-set
|
||||||
|
|
||||||
QWeb rendering can be used for many tasks. As a result, customizations
|
QWeb can be extended like any OpenERP model and new attributes can be
|
||||||
made by one task context (to either the main qweb rendering or to specific
|
added.
|
||||||
fields rendering) could break other tasks.
|
|
||||||
|
|
||||||
To avoid that, ``ir.qweb`` was consciously made inheritable and the "root"
|
|
||||||
of an object hierarchy. If you need extensions or alterations which could
|
|
||||||
be incompatible with other subsystems, you should create a local object
|
|
||||||
inheriting from ``ir.qweb`` and customize that.
|
|
||||||
|
|
||||||
If you need to customize t-fields rendering, subclass the ir.qweb.field
|
If you need to customize t-fields rendering, subclass the ir.qweb.field
|
||||||
model (and its sub-models) then override :meth:`~.get_converter_for` to
|
model (and its sub-models) then override :meth:`~.get_converter_for` to
|
||||||
fetch the right field converters for your qweb model.
|
fetch the right field converters for your qweb model.
|
||||||
|
|
||||||
|
Beware that if you need extensions or alterations which could be
|
||||||
|
incompatible with other subsystems, you should create a local object
|
||||||
|
inheriting from ``ir.qweb`` and customize that.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_name = 'ir.qweb'
|
_name = 'ir.qweb'
|
||||||
|
@ -121,7 +124,7 @@ class QWeb(orm.AbstractModel):
|
||||||
def register_tag(self, tag, func):
|
def register_tag(self, tag, func):
|
||||||
self._render_tag[tag] = func
|
self._render_tag[tag] = func
|
||||||
|
|
||||||
def load_document(self, x, into, context):
|
def load_document(self, x, qcontext):
|
||||||
"""
|
"""
|
||||||
Loads an XML document and installs any contained template in the engine
|
Loads an XML document and installs any contained template in the engine
|
||||||
"""
|
"""
|
||||||
|
@ -134,18 +137,20 @@ class QWeb(orm.AbstractModel):
|
||||||
|
|
||||||
for n in dom.documentElement.childNodes:
|
for n in dom.documentElement.childNodes:
|
||||||
if n.nodeType == self.node.ELEMENT_NODE and n.getAttribute('t-name'):
|
if n.nodeType == self.node.ELEMENT_NODE and n.getAttribute('t-name'):
|
||||||
self.add_template(into, str(n.getAttribute("t-name")), n, context)
|
name = str(n.getAttribute("t-name"))
|
||||||
|
|
||||||
|
qcontext.templates[name] = n
|
||||||
|
|
||||||
def add_template(self, into, name, node, context):
|
def get_template(self, name, qcontext):
|
||||||
into[name] = node
|
if qcontext.loader and name not in qcontext.templates:
|
||||||
|
xml_doc = qcontext.loader(name)
|
||||||
|
self.load_document(xml_doc, qcontext=qcontext)
|
||||||
|
|
||||||
def get_template(self, name, context):
|
if name in qcontext.templates:
|
||||||
if context.loader and name not in context.templates:
|
return qcontext.templates[name]
|
||||||
xml_doc = context.loader(name)
|
|
||||||
self.load_document(xml_doc, into=context.templates, context=context)
|
|
||||||
|
|
||||||
if name in context.templates:
|
import pdb
|
||||||
return context.templates[name]
|
pdb.set_trace()
|
||||||
|
|
||||||
e = KeyError('qweb: template "%s" not found' % name)
|
e = KeyError('qweb: template "%s" not found' % name)
|
||||||
setattr(e, 'qweb_template', name)
|
setattr(e, 'qweb_template', name)
|
||||||
|
@ -191,32 +196,19 @@ class QWeb(orm.AbstractModel):
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@openerp.tools.ormcache()
|
|
||||||
def get_template_xmlid(self, cr, uid, id):
|
|
||||||
imd = self.pool['ir.model.data']
|
|
||||||
domain = [('model', '=', 'ir.ui.view'), ('res_id', '=', id)]
|
|
||||||
xmlid = imd.search_read(cr, uid, domain, ['module', 'name'])[0]
|
|
||||||
return '%s.%s' % (xmlid['module'], xmlid['name'])
|
|
||||||
|
|
||||||
def render(self, cr, uid, id_or_xml_id, v=None, loader=None, context=None):
|
def render(self, cr, uid, id_or_xml_id, v=None, loader=None, context=None):
|
||||||
if isinstance(id_or_xml_id, list):
|
|
||||||
id_or_xml_id = id_or_xml_id[0]
|
|
||||||
tname = id_or_xml_id
|
|
||||||
if isinstance(id_or_xml_id, (int, long)):
|
|
||||||
tname = self.get_template_xmlid(cr, uid, tname)
|
|
||||||
|
|
||||||
if v is None:
|
if v is None:
|
||||||
v = {}
|
v = {}
|
||||||
if not isinstance(v, QWebContext):
|
if not isinstance(v, QWebContext):
|
||||||
v = QWebContext(cr, uid, v, loader=loader, context=context)
|
v = QWebContext(cr, uid, v, loader=loader, context=context)
|
||||||
v['__template__'] = tname
|
v['__template__'] = id_or_xml_id
|
||||||
stack = v.get('__stack__', [])
|
stack = v.get('__stack__', [])
|
||||||
if stack:
|
if stack:
|
||||||
v['__caller__'] = stack[-1]
|
v['__caller__'] = stack[-1]
|
||||||
stack.append(tname)
|
stack.append(id_or_xml_id)
|
||||||
v['__stack__'] = stack
|
v['__stack__'] = stack
|
||||||
v['xmlid'] = str(stack[0]) # Temporary fix
|
v['xmlid'] = str(stack[0]) # Temporary fix
|
||||||
return self.render_node(self.get_template(tname, v), v)
|
return self.render_node(self.get_template(id_or_xml_id, v), v)
|
||||||
|
|
||||||
def render_node(self, e, v):
|
def render_node(self, e, v):
|
||||||
r = ""
|
r = ""
|
||||||
|
@ -314,10 +306,13 @@ class QWeb(orm.AbstractModel):
|
||||||
|
|
||||||
def render_att_href(self, e, an, av, v):
|
def render_att_href(self, e, an, av, v):
|
||||||
return self.url_for(e, an, av, v)
|
return self.url_for(e, an, av, v)
|
||||||
|
|
||||||
def render_att_src(self, e, an, av, v):
|
def render_att_src(self, e, an, av, v):
|
||||||
return self.url_for(e, an, av, v)
|
return self.url_for(e, an, av, v)
|
||||||
|
|
||||||
def render_att_action(self, e, an, av, v):
|
def render_att_action(self, e, an, av, v):
|
||||||
return self.url_for(e, an, av, v)
|
return self.url_for(e, an, av, v)
|
||||||
|
|
||||||
def url_for(self, e, an, av, v):
|
def url_for(self, e, an, av, v):
|
||||||
if 'url_for' not in v:
|
if 'url_for' not in v:
|
||||||
raise KeyError("qweb: no 'url_for' found in context")
|
raise KeyError("qweb: no 'url_for' found in context")
|
||||||
|
@ -384,7 +379,7 @@ class QWeb(orm.AbstractModel):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def render_tag_call(self, e, t_att, g_att, v):
|
def render_tag_call(self, e, t_att, g_att, v):
|
||||||
d = v if 'import' in t_att else v.copy()
|
d = v.copy()
|
||||||
d[0] = self.render_element(e, t_att, g_att, d)
|
d[0] = self.render_element(e, t_att, g_att, d)
|
||||||
|
|
||||||
return self.render(None, None, self.eval_format(t_att["call"], d), d)
|
return self.render(None, None, self.eval_format(t_att["call"], d), d)
|
||||||
|
@ -423,6 +418,9 @@ class QWeb(orm.AbstractModel):
|
||||||
return self.pool.get('ir.qweb.field.' + field_type,
|
return self.pool.get('ir.qweb.field.' + field_type,
|
||||||
self.pool['ir.qweb.field'])
|
self.pool['ir.qweb.field'])
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# QWeb Fields converters
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
|
||||||
class FieldConverter(osv.AbstractModel):
|
class FieldConverter(osv.AbstractModel):
|
||||||
""" Used to convert a t-field specification into an output HTML field.
|
""" Used to convert a t-field specification into an output HTML field.
|
||||||
|
|
|
@ -40,6 +40,8 @@ from openerp.osv.orm import browse_record, browse_record_list
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
MOVABLE_BRANDING = ['data-oe-model', 'data-oe-id', 'data-oe-field', 'data-oe-xpath']
|
||||||
|
|
||||||
class view_custom(osv.osv):
|
class view_custom(osv.osv):
|
||||||
_name = 'ir.ui.view.custom'
|
_name = 'ir.ui.view.custom'
|
||||||
_order = 'create_date desc' # search(limit=1) should return the last customization
|
_order = 'create_date desc' # search(limit=1) should return the last customization
|
||||||
|
@ -71,7 +73,6 @@ class view(osv.osv):
|
||||||
'type': fields.selection([
|
'type': fields.selection([
|
||||||
('tree','Tree'),
|
('tree','Tree'),
|
||||||
('form','Form'),
|
('form','Form'),
|
||||||
('mdx','mdx'),
|
|
||||||
('graph', 'Graph'),
|
('graph', 'Graph'),
|
||||||
('calendar', 'Calendar'),
|
('calendar', 'Calendar'),
|
||||||
('diagram','Diagram'),
|
('diagram','Diagram'),
|
||||||
|
@ -183,11 +184,18 @@ class view(osv.osv):
|
||||||
# TODO: should be doable in a read and a write
|
# TODO: should be doable in a read and a write
|
||||||
for view_ in self.browse(cr, uid, ids, context=context):
|
for view_ in self.browse(cr, uid, ids, context=context):
|
||||||
if view_.model_data_id:
|
if view_.model_data_id:
|
||||||
view_.model_data_id.write({'noupdate': True})
|
self.pool.get('ir.model.data').write(cr, openerp.SUPERUSER_ID, view_.model_data_id.id, {'noupdate': True})
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# default view selection
|
def copy(self, cr, uid, id, default=None, context=None):
|
||||||
|
if not default:
|
||||||
|
default = {}
|
||||||
|
default.update({
|
||||||
|
'model_ids': [],
|
||||||
|
})
|
||||||
|
return super(view, self).copy(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
|
# default view selection
|
||||||
def default_view(self, cr, uid, model, view_type, context=None):
|
def default_view(self, cr, uid, model, view_type, context=None):
|
||||||
""" Fetches the default view for the provided (model, view_type) pair:
|
""" Fetches the default view for the provided (model, view_type) pair:
|
||||||
view with no parent (inherit_id=Fase) with the lowest priority.
|
view with no parent (inherit_id=Fase) with the lowest priority.
|
||||||
|
@ -207,8 +215,9 @@ class view(osv.osv):
|
||||||
return False
|
return False
|
||||||
return ids[0]
|
return ids[0]
|
||||||
|
|
||||||
# inheritance
|
#------------------------------------------------------
|
||||||
|
# Inheritance mecanism
|
||||||
|
#------------------------------------------------------
|
||||||
def get_inheriting_views_arch(self, cr, uid, view_id, model, context=None):
|
def get_inheriting_views_arch(self, cr, uid, view_id, model, context=None):
|
||||||
"""Retrieves the architecture of views that inherit from the given view, from the sets of
|
"""Retrieves the architecture of views that inherit from the given view, from the sets of
|
||||||
views that should currently be used in the system. During the module upgrade phase it
|
views that should currently be used in the system. During the module upgrade phase it
|
||||||
|
@ -422,8 +431,13 @@ class view(osv.osv):
|
||||||
|
|
||||||
return dict(view, arch=etree.tostring(arch, encoding='utf-8'))
|
return dict(view, arch=etree.tostring(arch, encoding='utf-8'))
|
||||||
|
|
||||||
# postprocessing: groups, modifiers, ...
|
#------------------------------------------------------
|
||||||
|
# Postprocessing: translation, groups and modifiers
|
||||||
|
#------------------------------------------------------
|
||||||
|
# TODO:
|
||||||
|
# - split postprocess so that it can be used instead of translate_qweb
|
||||||
|
# - remove group processing from ir_qweb
|
||||||
|
#------------------------------------------------------
|
||||||
def postprocess(self, cr, user, model, node, view_id, in_tree_view, model_fields, context=None):
|
def postprocess(self, cr, user, model, node, view_id, in_tree_view, model_fields, context=None):
|
||||||
"""Return the description of the fields in the node.
|
"""Return the description of the fields in the node.
|
||||||
|
|
||||||
|
@ -685,30 +699,32 @@ class view(osv.osv):
|
||||||
raise orm.except_orm('View error', msg)
|
raise orm.except_orm('View error', msg)
|
||||||
return arch, fields
|
return arch, fields
|
||||||
|
|
||||||
# view used as templates
|
#------------------------------------------------------
|
||||||
|
# QWeb template views
|
||||||
|
#------------------------------------------------------
|
||||||
@tools.ormcache_context(accepted_keys=('lang','inherit_branding', 'editable', 'translatable'))
|
@tools.ormcache_context(accepted_keys=('lang','inherit_branding', 'editable', 'translatable'))
|
||||||
def read_template(self, cr, uid, id_, context=None):
|
def read_template(self, cr, uid, xml_id, context=None):
|
||||||
try:
|
if '.' not in xml_id:
|
||||||
id_ = int(id_)
|
raise ValueError('Invalid template id: %r' % (xml_id,))
|
||||||
except ValueError:
|
|
||||||
if '.' not in id_:
|
|
||||||
raise ValueError('Invalid id: %r' % (id_,))
|
|
||||||
IMD = self.pool['ir.model.data']
|
|
||||||
m, _, n = id_.partition('.')
|
|
||||||
_, id_ = IMD.get_object_reference(cr, uid, m, n)
|
|
||||||
|
|
||||||
arch = self.read_combined(cr, uid, id_, fields=['arch'], context=context)['arch']
|
m, n = xml_id.split('.', 1)
|
||||||
|
_, view_id = self.pool['ir.model.data'].get_object_reference(cr, uid, m, n)
|
||||||
|
|
||||||
|
arch = self.read_combined(cr, uid, view_id, fields=['arch'], context=context)['arch']
|
||||||
arch_tree = etree.fromstring(arch)
|
arch_tree = etree.fromstring(arch)
|
||||||
|
|
||||||
if 'lang' in context:
|
if 'lang' in context:
|
||||||
arch_tree = self.translate_qweb(cr, uid, id_, arch_tree, context['lang'], context)
|
arch_tree = self.translate_qweb(cr, uid, view_id, arch_tree, context['lang'], context)
|
||||||
|
|
||||||
self.distribute_branding(arch_tree)
|
self.distribute_branding(arch_tree)
|
||||||
root = etree.Element('tpl')
|
root = etree.Element('templates')
|
||||||
root.append(arch_tree)
|
root.append(arch_tree)
|
||||||
arch = etree.tostring(root, encoding='utf-8', xml_declaration=True)
|
arch = etree.tostring(root, encoding='utf-8', xml_declaration=True)
|
||||||
return arch
|
return arch
|
||||||
|
|
||||||
|
def clear_cache(self):
|
||||||
|
self.read_template.clear_cache(self)
|
||||||
|
|
||||||
def distribute_branding(self, e, branding=None, parent_xpath='',
|
def distribute_branding(self, e, branding=None, parent_xpath='',
|
||||||
index_map=misc.ConstantMapping(1)):
|
index_map=misc.ConstantMapping(1)):
|
||||||
if e.get('t-ignore') or e.tag == 'head':
|
if e.get('t-ignore') or e.tag == 'head':
|
||||||
|
@ -768,8 +784,6 @@ class view(osv.osv):
|
||||||
text = h.unescape(text.strip())
|
text = h.unescape(text.strip())
|
||||||
if len(text) < 2 or (text.startswith('<!') and text.endswith('>')):
|
if len(text) < 2 or (text.startswith('<!') and text.endswith('>')):
|
||||||
return None
|
return None
|
||||||
# if text == 'Our Events':
|
|
||||||
# from pudb import set_trace;set_trace() ############################## Breakpoint ##############################
|
|
||||||
return Translations._get_source(cr, uid, 'website', 'view', lang, text, id_)
|
return Translations._get_source(cr, uid, 'website', 'view', lang, text, id_)
|
||||||
|
|
||||||
if arch.tag not in ['script']:
|
if arch.tag not in ['script']:
|
||||||
|
@ -788,16 +802,18 @@ class view(osv.osv):
|
||||||
self.translate_qweb(cr, uid, id_, node, lang, context)
|
self.translate_qweb(cr, uid, id_, node, lang, context)
|
||||||
return arch
|
return arch
|
||||||
|
|
||||||
def render(self, cr, uid, id_or_xml_id, values=None, engine='ir.qweb', context=None):
|
def render(self, cr, uid, xml_id, values=None, engine='ir.qweb', context=None):
|
||||||
if not context:
|
if not context:
|
||||||
context = {}
|
context = {}
|
||||||
|
|
||||||
def loader(name):
|
def loader(name):
|
||||||
return self.read_template(cr, uid, name, context=context)
|
return self.read_template(cr, uid, name, context=context)
|
||||||
|
|
||||||
return self.pool[engine].render(cr, uid, id_or_xml_id, values, loader=loader, context=context)
|
return self.pool[engine].render(cr, uid, xml_id, values, loader=loader, context=context)
|
||||||
|
|
||||||
# maybe used to print the workflow ?
|
#------------------------------------------------------
|
||||||
|
# Misc
|
||||||
|
#------------------------------------------------------
|
||||||
|
|
||||||
def graph_get(self, cr, uid, id, model, node_obj, conn_obj, src_node, des_node, label, scale, context=None):
|
def graph_get(self, cr, uid, id, model, node_obj, conn_obj, src_node, des_node, label, scale, context=None):
|
||||||
nodes=[]
|
nodes=[]
|
||||||
|
@ -866,14 +882,6 @@ class view(osv.osv):
|
||||||
'blank_nodes': blank_nodes,
|
'blank_nodes': blank_nodes,
|
||||||
'node_parent_field': _Model_Field,}
|
'node_parent_field': _Model_Field,}
|
||||||
|
|
||||||
def copy(self, cr, uid, id, default=None, context=None):
|
|
||||||
if not default:
|
|
||||||
default = {}
|
|
||||||
default.update({
|
|
||||||
'model_ids': [],
|
|
||||||
})
|
|
||||||
return super(view, self).copy(cr, uid, id, default, context=context)
|
|
||||||
|
|
||||||
def _validate_custom_views(self, cr, uid, model):
|
def _validate_custom_views(self, cr, uid, model):
|
||||||
"""Validate architecture of custom views (= without xml id) for a given model.
|
"""Validate architecture of custom views (= without xml id) for a given model.
|
||||||
This method is called at the end of registry update.
|
This method is called at the end of registry update.
|
||||||
|
@ -889,4 +897,4 @@ class view(osv.osv):
|
||||||
ids = map(itemgetter(0), cr.fetchall())
|
ids = map(itemgetter(0), cr.fetchall())
|
||||||
return self._check_xml(cr, uid, ids)
|
return self._check_xml(cr, uid, ids)
|
||||||
|
|
||||||
MOVABLE_BRANDING = ['data-oe-model', 'data-oe-id', 'data-oe-field', 'data-oe-xpath']
|
# vim:et:
|
||||||
|
|
|
@ -600,6 +600,7 @@ class users_implied(osv.osv):
|
||||||
if groups:
|
if groups:
|
||||||
# delegate addition of groups to add implied groups
|
# delegate addition of groups to add implied groups
|
||||||
self.write(cr, uid, [user_id], {'groups_id': groups}, context)
|
self.write(cr, uid, [user_id], {'groups_id': groups}, context)
|
||||||
|
self.pool['ir.ui.view'].clear_cache()
|
||||||
return user_id
|
return user_id
|
||||||
|
|
||||||
def write(self, cr, uid, ids, values, context=None):
|
def write(self, cr, uid, ids, values, context=None):
|
||||||
|
@ -612,6 +613,7 @@ class users_implied(osv.osv):
|
||||||
gs = set(concat([g.trans_implied_ids for g in user.groups_id]))
|
gs = set(concat([g.trans_implied_ids for g in user.groups_id]))
|
||||||
vals = {'groups_id': [(4, g.id) for g in gs]}
|
vals = {'groups_id': [(4, g.id) for g in gs]}
|
||||||
super(users_implied, self).write(cr, uid, [user.id], vals, context)
|
super(users_implied, self).write(cr, uid, [user.id], vals, context)
|
||||||
|
self.pool['ir.ui.view'].clear_cache()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
|
|
@ -168,7 +168,7 @@ class WebRequest(object):
|
||||||
if not k.startswith("_ignored_"))
|
if not k.startswith("_ignored_"))
|
||||||
|
|
||||||
self.func = func
|
self.func = func
|
||||||
self.func_request_type = func.exposed
|
self.func_request_type = func.routing['type']
|
||||||
self.func_arguments = arguments
|
self.func_arguments = arguments
|
||||||
self.auth_method = auth
|
self.auth_method = auth
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ class WebRequest(object):
|
||||||
warnings.warn('please use request.registry and request.cr directly', DeprecationWarning)
|
warnings.warn('please use request.registry and request.cr directly', DeprecationWarning)
|
||||||
yield (self.registry, self.cr)
|
yield (self.registry, self.cr)
|
||||||
|
|
||||||
def route(route, type="http", auth="user", methods=None):
|
def route(route=None, **kw):
|
||||||
"""
|
"""
|
||||||
Decorator marking the decorated method as being a handler for requests. The method must be part of a subclass
|
Decorator marking the decorated method as being a handler for requests. The method must be part of a subclass
|
||||||
of ``Controller``.
|
of ``Controller``.
|
||||||
|
@ -226,16 +226,16 @@ def route(route, type="http", auth="user", methods=None):
|
||||||
configuration indicating the current database nor the current user.
|
configuration indicating the current database nor the current user.
|
||||||
:param methods: A sequence of http methods this route applies to. If not specified, all methods are allowed.
|
:param methods: A sequence of http methods this route applies to. If not specified, all methods are allowed.
|
||||||
"""
|
"""
|
||||||
assert type in ["http", "json"]
|
routing = kw.copy()
|
||||||
|
assert not 'type' in routing or routing['type'] in ("http", "json")
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
if isinstance(route, list):
|
if route:
|
||||||
f.routes = route
|
if isinstance(route, list):
|
||||||
else:
|
routes = route
|
||||||
f.routes = [route]
|
else:
|
||||||
f.methods = methods
|
routes = [route]
|
||||||
f.exposed = type
|
routing['routes'] = routes
|
||||||
if getattr(f, "auth", None) is None:
|
f.routing = routing
|
||||||
f.auth = auth
|
|
||||||
return f
|
return f
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
@ -388,11 +388,10 @@ def jsonrequest(f):
|
||||||
|
|
||||||
Use the ``route()`` decorator instead.
|
Use the ``route()`` decorator instead.
|
||||||
"""
|
"""
|
||||||
f.combine = True
|
|
||||||
base = f.__name__.lstrip('/')
|
base = f.__name__.lstrip('/')
|
||||||
if f.__name__ == "index":
|
if f.__name__ == "index":
|
||||||
base = ""
|
base = ""
|
||||||
return route([base, base + "/<path:_ignored_path>"], type="json", auth="user")(f)
|
return route([base, base + "/<path:_ignored_path>"], type="json", auth="user", combine=True)(f)
|
||||||
|
|
||||||
class HttpRequest(WebRequest):
|
class HttpRequest(WebRequest):
|
||||||
""" Regular GET/POST request
|
""" Regular GET/POST request
|
||||||
|
@ -444,11 +443,10 @@ def httprequest(f):
|
||||||
|
|
||||||
Use the ``route()`` decorator instead.
|
Use the ``route()`` decorator instead.
|
||||||
"""
|
"""
|
||||||
f.combine = True
|
|
||||||
base = f.__name__.lstrip('/')
|
base = f.__name__.lstrip('/')
|
||||||
if f.__name__ == "index":
|
if f.__name__ == "index":
|
||||||
base = ""
|
base = ""
|
||||||
return route([base, base + "/<path:_ignored_path>"], type="http", auth="user")(f)
|
return route([base, base + "/<path:_ignored_path>"], type="http", auth="user", combine=True)(f)
|
||||||
|
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
# Controller and route registration
|
# Controller and route registration
|
||||||
|
@ -501,13 +499,22 @@ def routing_map(modules, nodb_only, converters=None):
|
||||||
o = cls()
|
o = cls()
|
||||||
members = inspect.getmembers(o)
|
members = inspect.getmembers(o)
|
||||||
for mk, mv in members:
|
for mk, mv in members:
|
||||||
if inspect.ismethod(mv) and getattr(mv, 'exposed', False) and (not nodb_only or nodb_only == (mv.auth == "none")):
|
if inspect.ismethod(mv) and hasattr(mv, 'routing'):
|
||||||
for url in mv.routes:
|
routing = dict(type='http', auth='user', methods=None)
|
||||||
if getattr(mv, "combine", False):
|
for claz in reversed(mv.im_class.mro()):
|
||||||
url = o._cp_path.rstrip('/') + '/' + url.lstrip('/')
|
fn = getattr(claz, mv.func_name, None)
|
||||||
if url.endswith("/") and len(url) > 1:
|
if fn and hasattr(fn, 'routing'):
|
||||||
url = url[: -1]
|
routing.update(fn.routing)
|
||||||
routing_map.add(werkzeug.routing.Rule(url, endpoint=mv, methods=mv.methods))
|
mv.routing.update(routing)
|
||||||
|
assert 'routes' in mv.routing
|
||||||
|
if not nodb_only or nodb_only == (mv.routing['auth'] == "none"):
|
||||||
|
for url in mv.routing['routes']:
|
||||||
|
if mv.routing.get("combine", False):
|
||||||
|
# deprecated
|
||||||
|
url = o._cp_path.rstrip('/') + '/' + url.lstrip('/')
|
||||||
|
if url.endswith("/") and len(url) > 1:
|
||||||
|
url = url[: -1]
|
||||||
|
routing_map.add(werkzeug.routing.Rule(url, endpoint=mv, methods=mv.routing['methods']))
|
||||||
return routing_map
|
return routing_map
|
||||||
|
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
|
|
@ -106,7 +106,7 @@ class WorkflowInstance(object):
|
||||||
for cur_instance_id, cur_model_name, cur_record_id in cr.fetchall():
|
for cur_instance_id, cur_model_name, cur_record_id in cr.fetchall():
|
||||||
cur_record = Record(cur_model_name, cur_record_id)
|
cur_record = Record(cur_model_name, cur_record_id)
|
||||||
for act_name in act_names:
|
for act_name in act_names:
|
||||||
WorkflowInstance(self.session, cur_record, {'id':cur_instance_id}).validate('subflow.{}'.format(act_name[0]))
|
WorkflowInstance(self.session, cur_record, {'id':cur_instance_id}).validate('subflow.%s' % act_name[0])
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue