[FIX] api: avoid to return all fields *2many in onchanges

When an onchange returns a change in a 2many field line (a '1' tuple, update), avoid to return all fields of the *2many field but only the altered field.

Otherwise, the web client regard all the fields of the 2many as dirty, and try to write on all fields (even if the value is the same, thus)

opw-615062
This commit is contained in:
Denis Ledoux 2014-11-14 14:24:11 +01:00
parent f469e8e09f
commit 999ed04c40
3 changed files with 10 additions and 12 deletions

View File

@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013 OpenERP (<http://www.openerp.com>).
# Copyright (C) 2013-2014 OpenERP (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -717,7 +717,7 @@ class Environment(object):
self.cache = defaultdict(dict) # {field: {id: value, ...}, ...}
self.prefetch = defaultdict(set) # {model_name: set(id), ...}
self.computed = defaultdict(set) # {field: set(id), ...}
self.dirty = set() # set(record)
self.dirty = defaultdict(set) # {record: set(field_name), ...}
self.all = envs
envs.add(self)
return self

View File

@ -791,7 +791,7 @@ class Field(object):
if env.in_onchange:
for invf in self.inverse_fields:
invf._update(value, record)
record._dirty = True
record._set_dirty_by(self.name)
# determine more dependent fields, and invalidate them
if self.relational:
@ -1578,7 +1578,8 @@ class _RelationalMulti(_Relational):
# add new and existing records
for record in value:
if not record.id or record._dirty:
values = dict((k, v) for k, v in record._cache.iteritems() if k in fnames)
dirty_fields = record.env.dirty[record]
values = dict((k, v) for k, v in record._cache.iteritems() if k in fnames and k in dirty_fields)
values = record._convert_to_write(values)
if not record.id:
result.append((0, 0, values))

View File

@ -5320,15 +5320,12 @@ class BaseModel(object):
def _dirty(self):
""" Return whether any record in `self` is dirty. """
dirty = self.env.dirty
return any(record in dirty for record in self)
return any(bool(dirty.get(record)) for record in self)
@_dirty.setter
def _dirty(self, value):
""" Mark the records in `self` as dirty. """
if value:
map(self.env.dirty.add, self)
else:
map(self.env.dirty.discard, self)
def _set_dirty_by(self, field_name):
dirty = self.env.dirty
for record in self:
dirty[record].add(field_name)
#
# "Dunder" methods