diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-10-13 13:13:11 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-10-13 13:13:11 +0200 |
| commit | 1da064a1d34b48ff23d8cdf5a1c189c8bbb4eb64 (patch) | |
| tree | d832553531790ca342cda3b03e6c44097717ff43 /odoo | |
| parent | 119ae9b5dcaea577bfd91b36565b764990b9de02 (diff) | |
| parent | 8ee9024a4c888647df9e18861fe5e58b68947469 (diff) | |
[MERGE] forward port branch saas-16 up to 8ee9024a4c8
Diffstat (limited to 'odoo')
| -rw-r--r-- | odoo/addons/base/ir/ir_qweb/qweb.py | 52 | ||||
| -rw-r--r-- | odoo/addons/base/res/res.lang.csv | 2 | ||||
| -rw-r--r-- | odoo/fields.py | 45 | ||||
| -rw-r--r-- | odoo/models.py | 17 |
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 |
