diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index dfa061588c0..73d1c7e5a3d 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -171,8 +171,12 @@ class Session(openerpweb.Controller): a list of fields to group by, potentially empty (in which case no group by should be performed) """ - context = req.session.eval_context(openerpweb.nonliterals.CompoundContext(*contexts)) - domain = req.session.eval_domain(openerpweb.nonliterals.CompoundDomain(*(domains or [])), context) + contexts = contexts or [] + domains = domains or [] + e_context = dict(reduce(lambda x, y: x + y, [openerpweb.nonliterals.get_eval_context(x).items() for x in contexts])) + context, domain = eval_context_and_domain(req.session, + openerpweb.nonliterals.CompoundContext(*contexts).set_eval_context(e_context), + openerpweb.nonliterals.CompoundDomain(*domains)) group_by_sequence = [] for candidate in (group_by_seq or []): @@ -233,7 +237,8 @@ class Session(openerpweb.Controller): def eval_context_and_domain(session, context, domain=None): e_context = session.eval_context(context) - e_domain = session.eval_domain(domain or [], e_context) + eval_context = openerpweb.nonliterals.get_eval_context(context) + e_domain = session.eval_domain(domain or [], dict(eval_context.items() + e_context.items())) return (e_context, e_domain) diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js index b0e757c8305..73c88043913 100644 --- a/addons/base/static/src/js/data.js +++ b/addons/base/static/src/js/data.js @@ -590,6 +590,7 @@ openerp.base.ReadOnlyDataSetSearch = openerp.base.DataSetSearch.extend({ openerp.base.CompoundContext = function() { this.__ref = "compound_context"; this.__contexts = []; + this.__eval_context = null; var self = this; _.each(arguments, function(x) { self.add(x); @@ -602,6 +603,13 @@ openerp.base.CompoundContext.prototype.add = function(context) { this.__contexts.push(context); return this; }; +openerp.base.CompoundContext.prototype.set_eval_context = function(eval_context) { + this.__eval_context = eval_context; + return this; +}; +openerp.base.CompoundContext.prototype.get_eval_context = function() { + return this.__eval_context; +}; openerp.base.CompoundDomain = function() { this.__ref = "compound_domain"; diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index ff18baef404..b2c74c920c3 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -417,6 +417,13 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV } else { this.on_button_new(); } + }, + get_fields_values: function() { + var values = {}; + _.each(this.fields, function(value, key) { + values[key] = value.get_value(); + }); + return values; } }); @@ -1079,7 +1086,8 @@ var build_relation_context = function(relation_field) { var action = relation_field.view.view_manager.action || {}; var a_context = action.context || {}; var f_context = relation_field.field.context || {}; - var ctx = new openerp.base.CompoundContext(a_context).add(f_context); + var fields_values = relation_field.view.get_fields_values(); + var ctx = new openerp.base.CompoundContext(a_context).add(f_context).set_eval_context(fields_values); return ctx; } @@ -1301,7 +1309,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ if (this.tmp_value instanceof Array) { return this.tmp_value[0]; } - return this.tmp_value === null ? false : this.tmp_value; + return this.tmp_value ? this.tmp_value : false; } if (this.value === undefined) throw "theorically unreachable state"; diff --git a/openerpweb/nonliterals.py b/openerpweb/nonliterals.py index f999a30e20d..f1aef0a56dc 100644 --- a/openerpweb/nonliterals.py +++ b/openerpweb/nonliterals.py @@ -36,7 +36,8 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder): elif isinstance(object, CompoundContext): return { '__ref': 'compound_context', - '__contexts': object.contexts + '__contexts': object.contexts, + '__eval_context': object.get_eval_context() } raise TypeError('Could not encode unknown non-literal %s' % object) @@ -67,6 +68,7 @@ def non_literal_decoder(dct): ccontext = CompoundContext() for el in dct["__contexts"]: ccontext.contexts.append(non_literal_decoder(el)) + ccontext.set_eval_context(non_literal_decoder(dct.get("__eval_context") or {})) return ccontext return dct @@ -121,7 +123,7 @@ class Domain(BaseDomain): ctx = self.session.evaluation_context(context) if self.own: ctx.update(self.own) - return eval(self.get_domain_string(), ctx) + return eval(self.get_domain_string(), SuperDict(ctx)) class Context(BaseContext): def __init__(self, session, context_string=None, key=None): @@ -167,7 +169,19 @@ class Context(BaseContext): if self.own: ctx.update(self.own) return eval(self.get_context_string(), - ctx) + SuperDict(ctx)) + +def SuperDict(dict): + def __getattr__(self, name): + try: + return self[name] + except KeyError: + raise AttributeError(name) + def __getitem__(self, key): + tmp = super(dict, self)[key] + if isinstance(tmp, dict): + return SuperDict(tmp) + return tmp class CompoundDomain(BaseDomain): def __init__(self, *domains): @@ -197,16 +211,23 @@ class CompoundDomain(BaseDomain): def add(self, domain): self.domains.append(domain) return self + +def get_eval_context(context): + if isinstance(context, CompoundContext): + return context.get_eval_context() or {} + return {} class CompoundContext(BaseContext): def __init__(self, *contexts): self.contexts = [] + self.eval_context = None self.session = None for context in contexts: self.add(context) def evaluate(self, context=None): ctx = dict(context or {}) + ctx.update(self.get_eval_context() or {}) final_context = {} for context_to_eval in self.contexts: if not isinstance(context_to_eval, (dict, BaseContext)): @@ -225,6 +246,15 @@ class CompoundContext(BaseContext): return final_context def add(self, context): - self.contexts.append(context) + if isinstance(context, BaseContext): + self.contexts = self.contexts + context.contexts + else: + self.contexts.append(context) + return self + + def set_eval_context(self, eval_context): + self.eval_context = eval_context return self + def get_eval_context(self): + return self.eval_context