[FIX] fields: invalidate x2many fields with a domain

Invalidate the cache of a x2many field when any of the fields appearing in its
domain is modified.  Use the invalidation triggers mechanism for that purpose.
This commit is contained in:
Raphael Collet 2016-05-06 10:47:29 +02:00
parent 7923999f12
commit 5676d8121d
3 changed files with 21 additions and 1 deletions

View File

@ -143,6 +143,8 @@ class Discussion(models.Model):
participants = fields.Many2many('res.users')
messages = fields.One2many('test_new_api.message', 'discussion')
message_changes = fields.Integer(string='Message changes')
important_messages = fields.One2many('test_new_api.message', 'discussion',
domain=[('important', '=', True)])
@api.onchange('moderator')
def _onchange_moderator(self):
@ -167,6 +169,7 @@ class Message(models.Model):
author_partner = fields.Many2one(
'res.partner', compute='_compute_author_partner',
search='_search_author_partner')
important = fields.Boolean()
@api.one
@api.constrains('author', 'discussion')

View File

@ -448,6 +448,14 @@ class TestNewFields(common.TransactionCase):
[('author_partner.name', '=', 'Demo User')])
self.assertEqual(messages, self.env.ref('test_new_api.message_0_1'))
def test_60_x2many_domain(self):
""" test the cache consistency of a x2many field with a domain """
discussion = self.env.ref('test_new_api.discussion_0')
message = discussion.messages[0]
self.assertNotIn(message, discussion.important_messages)
message.important = True
self.assertIn(message, discussion.important_messages)
class TestMagicFields(common.TransactionCase):

View File

@ -971,7 +971,7 @@ class Field(object):
# invalidate the fields that depend on self, and prepare recomputation
spec = [(self, records._ids)]
for field, path in self._triggers:
if path and field.store:
if path and field.compute and field.store:
# don't move this line to function top, see log
env = records.env(user=SUPERUSER_ID, context={'active_test': False})
target = env[field.model_name].search([(path, 'in', records.ids)])
@ -1723,6 +1723,15 @@ class _RelationalMulti(_Relational):
for record in records:
record[self.name] = record[self.name].filtered(accessible)
def setup_triggers(self, env):
super(_RelationalMulti, self).setup_triggers(env)
# also invalidate self when fields appearing in the domain are modified
if isinstance(self.domain, list):
comodel = env[self.comodel_name]
for arg in self.domain:
if isinstance(arg, (tuple, list)) and isinstance(arg[0], basestring):
self._setup_dependency([self.name], comodel, arg[0].split('.'))
class One2many(_RelationalMulti):
""" One2many field; the value of such a field is the recordset of all the