summaryrefslogtreecommitdiff
path: root/odoo
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2017-10-13 13:13:11 +0200
committerChristophe Simonis <chs@odoo.com>2017-10-13 13:13:11 +0200
commit1da064a1d34b48ff23d8cdf5a1c189c8bbb4eb64 (patch)
treed832553531790ca342cda3b03e6c44097717ff43 /odoo
parent119ae9b5dcaea577bfd91b36565b764990b9de02 (diff)
parent8ee9024a4c888647df9e18861fe5e58b68947469 (diff)
[MERGE] forward port branch saas-16 up to 8ee9024a4c8
Diffstat (limited to 'odoo')
-rw-r--r--odoo/addons/base/ir/ir_qweb/qweb.py52
-rw-r--r--odoo/addons/base/res/res.lang.csv2
-rw-r--r--odoo/fields.py45
-rw-r--r--odoo/models.py17
4 files changed, 71 insertions, 45 deletions
diff --git a/odoo/addons/base/ir/ir_qweb/qweb.py b/odoo/addons/base/ir/ir_qweb/qweb.py
index 43c10fe19f0..a773daf600e 100644
--- a/odoo/addons/base/ir/ir_qweb/qweb.py
+++ b/odoo/addons/base/ir/ir_qweb/qweb.py
@@ -1135,7 +1135,26 @@ class QWeb(object):
def _compile_directive_esc(self, el, options):
field_options = self._compile_widget_options(el, 'esc')
- content = self._compile_widget(el, el.attrib.pop('t-esc'), field_options, 'escape')
+ content = self._compile_widget(el, el.attrib.pop('t-esc'), field_options)
+ if not field_options:
+ # if content is not False and if content is not None:
+ # content = escape(pycompat.to_text(content))
+ content.append(self._if_content_is_not_Falsy([
+ ast.Assign(
+ targets=[ast.Name(id='content', ctx=ast.Store())],
+ value=ast.Call(
+ func=ast.Name(id='escape', ctx=ast.Load()),
+ args=[ast.Call(
+ func=ast.Name(id='to_text', ctx=ast.Load()),
+ args=[ast.Name(id='content', ctx=ast.Load())], keywords=[],
+ starargs=None, kwargs=None
+ )],
+ keywords=[],
+ starargs=None, kwargs=None
+ )
+ )],
+ []
+ ))
return content + self._compile_widget_value(el, options)
def _compile_directive_raw(self, el, options):
@@ -1143,33 +1162,8 @@ class QWeb(object):
content = self._compile_widget(el, el.attrib.pop('t-raw'), field_options)
return content + self._compile_widget_value(el, options)
+ # escape attribute is deprecated and will remove after v11
def _compile_widget(self, el, expression, field_options, escape=None):
- # if isinstance(value, string_types):
- # value = escape(to_text(value))
- escaped = ast.If(
- test=ast.Call(
- func=ast.Name(id='isinstance', ctx=ast.Load()),
- args=[
- ast.Name(id='content', ctx=ast.Load()),
- ast.Name(id='string_types', ctx=ast.Load())
- ], keywords=[],
- starargs=None, kwargs=None
- ),
- body=[ast.Assign(
- targets=[ast.Name(id='content', ctx=ast.Store())],
- value=ast.Call(
- func=ast.Name(id=escape, ctx=ast.Load()),
- args=[ast.Call(
- func=ast.Name(id='to_text', ctx=ast.Load()),
- args=[ast.Name(id='content', ctx=ast.Load())], keywords=[],
- starargs=None, kwargs=None
- )], keywords=[],
- starargs=None, kwargs=None
- ) if escape else ast.Name(id='content', ctx=ast.Load())
- )],
- orelse=[]
- )
-
if field_options:
return [
# value = t-(esc|raw)
@@ -1177,7 +1171,6 @@ class QWeb(object):
targets=[ast.Name(id='content', ctx=ast.Store())],
value=self._compile_expr0(expression)
),
- escaped,
# t_attrs, content, force_display = self._get_widget(value, expression, tagName, field options, template options, values)
ast.Assign(
targets=[ast.Tuple(elts=[
@@ -1221,8 +1214,7 @@ class QWeb(object):
self._compile_expr0(expression),
ast.Name(id='None', ctx=ast.Load()),
], ctx=ast.Load())
- ),
- escaped
+ )
]
# for backward compatibility to remove after v10
diff --git a/odoo/addons/base/res/res.lang.csv b/odoo/addons/base/res/res.lang.csv
index 44b1406b753..e04af8271b7 100644
--- a/odoo/addons/base/res/res.lang.csv
+++ b/odoo/addons/base/res/res.lang.csv
@@ -21,7 +21,7 @@
"base.lang_fr_BE","French (BE) / Français (BE)","fr_BE","fr_BE","Left-to-Right","[3,0]",",",".","%d/%m/%Y","%H:%M:%S","True"
"base.lang_fr_CA","French (CA) / Français (CA)","fr_CA","fr_CA","Left-to-Right","[3,0]",","," ","%Y-%m-%d","%H:%M:%S","True"
"base.lang_fr_CH","French (CH) / Français (CH)","fr_CH","fr_CH","Left-to-Right","[3,0]",".","'","%d. %m. %Y","%H:%M:%S","True"
-"base.lang_fr","French / Français","fr_FR","fr","Left-to-Right","[3,0]",","," ","%d/%m/%Y","%H:%M:%S","True"
+"base.lang_fr","French / Français","fr_FR","fr","Left-to-Right","[3,0]",","," ","%d/%m/%Y","%H:%M:%S","True"
"base.lang_gl_ES","Galician / Galego","gl_ES","gl_ES","Left-to-Right","[]",",",,"%d/%m/%Y","%H:%M:%S","True"
"base.lang_ka_GE","Georgian / ქართული ენა","ka_GE","ka_GE","Left-to-Right","[3,0]",",",".","%m/%d/%Y","%H:%M:%S","True"
"base.lang_de","German / Deutsch","de_DE","de","Left-to-Right","[3,0]",",",".","%d.%m.%Y","%H:%M:%S","True"
diff --git a/odoo/fields.py b/odoo/fields.py
index f04c4139b6f..4c41c938637 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -52,6 +52,10 @@ def copy_cache(records, env):
if value and field.type in ('many2one', 'one2many', 'many2many', 'reference'):
todo.update(field.convert_to_record(value, record))
+def first(records):
+ """ Return the first record in ``records``, with the same prefetching. """
+ return next(iter(records)) if len(records) > 1 else records
+
def resolve_mro(model, name, predicate):
""" Return the list of successively overridden values of attribute ``name``
@@ -558,12 +562,41 @@ class Field(MetaField('DummyField', (object,), {})):
""" Compute the related field ``self`` on ``records``. """
# when related_sudo, bypass access rights checks when reading values
others = records.sudo() if self.related_sudo else records
- for record, other in pycompat.izip(records, others):
- if not record.id and record.env != other.env:
- # draft records: copy record's cache to other's cache first
- copy_cache(record, other.env)
- other, field = self.traverse_related(other)
- record[self.name] = other[field.name]
+ # copy the cache of draft records into others' cache
+ if records.env != others.env:
+ copy_cache(records - records.filtered('id'), others.env)
+ #
+ # Traverse fields one by one for all records, in order to take advantage
+ # of prefetching for each field access. In order to clarify the impact
+ # of the algorithm, consider traversing 'foo.bar' for records a1 and a2,
+ # where 'foo' is already present in cache for a1, a2. Initially, both a1
+ # and a2 are marked for prefetching. As the commented code below shows,
+ # traversing all fields one record at a time will fetch 'bar' one record
+ # at a time.
+ #
+ # b1 = a1.foo # mark b1 for prefetching
+ # v1 = b1.bar # fetch/compute bar for b1
+ # b2 = a2.foo # mark b2 for prefetching
+ # v2 = b2.bar # fetch/compute bar for b2
+ #
+ # On the other hand, traversing all records one field at a time ensures
+ # maximal prefetching for each field access.
+ #
+ # b1 = a1.foo # mark b1 for prefetching
+ # b2 = a2.foo # mark b2 for prefetching
+ # v1 = b1.bar # fetch/compute bar for b1, b2
+ # v2 = b2.bar # value already in cache
+ #
+ # This difference has a major impact on performance, in particular in
+ # the case where 'bar' is a computed field that takes advantage of batch
+ # computation.
+ #
+ values = list(others)
+ for name in self.related[:-1]:
+ values = [first(value[name]) for value in values]
+ # assign final values to records
+ for record, value in pycompat.izip(records, values):
+ record[self.name] = value[self.related_field.name]
def _inverse_related(self, records):
""" Inverse the related field ``self`` on ``records``. """
diff --git a/odoo/models.py b/odoo/models.py
index 7a056c326e5..dea095cd4c9 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -3377,14 +3377,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
id_new, = cr.fetchone()
self = self.browse(id_new)
- if self.env.lang and self.env.lang != 'en_US':
- # add translations for self.env.lang
- for name, val in vals.items():
- field = self._fields[name]
- if field.store and field.column_type and field.translate is True:
- tname = "%s,%s" % (self._name, name)
- self.env['ir.translation']._set_ids(tname, 'model', self.env.lang, self.ids, val, val)
-
if self._parent_store and not self._context.get('defer_parent_store_computation'):
if self.pool._init:
self.pool._init_parent[self._name] = True
@@ -3446,6 +3438,15 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
self.recompute()
self.check_access_rule('create')
+
+ if self.env.lang and self.env.lang != 'en_US':
+ # add translations for self.env.lang
+ for name, val in vals.items():
+ field = self._fields[name]
+ if field.store and field.column_type and field.translate is True:
+ tname = "%s,%s" % (self._name, name)
+ self.env['ir.translation']._set_ids(tname, 'model', self.env.lang, self.ids, val, val)
+
return id_new
# TODO: ameliorer avec NULL