Compute method is called multiple times?

僤鯓⒐⒋嵵緔 提交于 2019-12-06 03:52:17

I think that your problem is elsewhere. Never mind how many time Odoo invokes your _compute_separated_chars method you have to return correctly the value of the separated_chars field. And where is the problem for me?

The value of the separated_chars field is calculated inside your _compute_separated_chars method. So, in the time of invocation of this method the value of this field is undefined! You cannot rely on it. But you do - you use this value for deleting the existing records.

If you debug furthermore you'll see that when the method is executed, the value of separated_chars is probably empty. In this way you delete nothing. If you count the number of rows in your database table sync_test_subject_a you'll probably see that they are increasing with every execution of your _compute... method.

Try to elaborate a little bit different logic for your many2many relation field computation.

I'm giving you hereafter a cleaner version of your method but your problem still exists. The separated_chars are not unlinked because in the time of invocation self.separated_chars in empty!

@api.one
@api.depends('chars')
def _compute_separated_chars(self):
    a_model = self.env['sync.test.subject.a']
    if not self.chars:
        return
    self.separated_chars.unlink()
    for character in self.chars:
        self.separated_chars += \
                a_model.create({'name': character})
William Wino

Allright, to sum this up. This problem has reached its dead end. I can't do anything else to fix this without editing Odoo's source code.

The unjustifiable things that Odoo does are as follows:

  1. The system strangely calls the compute method again from within the method itself if you assign ids to the compute field (which works by the way). (See Andrei's answer for an alternative way to assign many2many values that won't trigger this problem)
  2. The system restricts any changes to any other field or model except the field that related to the compute method from the compute method.
  3. The system updates the computed field everytime there are changes to any other field (even those fields that aren't related to the computed fields).

Andrei Boyanov's alternative implementation of the method fixes some of my problems. But there is one problem remains and I move the problem to Another Question Thread.

This behavior is actually caused by the method calling itself again every time I try to update the separated_chars field. What causes this behavior is unknown as the trigger of the method is the change of chars field as specified in this line of code: @api.depends('chars').

I dirty patched this with a lock field (Boolean) that is set True before updating the separated_chars field so that when _compute_separated_chars is called again it won't do anything.

Code:

class sync_test_subject_b(models.Model):

    _name           = "sync.test.subject.b"

    chars           = fields.Char('Characters')
    separated_chars = fields.Many2many('sync.test.subject.a',string='Separated Name', store=True, compute='_compute_separated_chars')
    lock            = fields.Boolean('Lock')

    @api.depends('chars')
    def _compute_separated_chars(self):
        if not self.lock:            

            print "CHAR SEPARATION BEGIN"
            sync_test_subject_a_pool = self.env['sync.test.subject.a']

            print "SEPARATE CHARS"
            # SEPARATE CHARS
            characters = []
            if self.chars:
                for character in self.chars:
                    characters.append(character)

            print "DELETE CURRENT CHARS"
            # DELETE CURRENT MANY2MANY LINK
            self.separated_chars.unlink()

            print "DELETE EXISTING sync_test_subject_a THAT ARE RELATED TO CURRENT SELF"
            # DELETE EXISTING sync_test_subject_a THAT ARE RELATED TO CURRENT SELF
            deleted_separated_char_ids = []
            for separated_char in self.separated_chars:
                deleted_separated_char_ids.append(separated_char.sync_test_subject_a_id.id)

            sync_test_subject_a_pool.browse(deleted_separated_char_ids).unlink()

            print "INSERT NEW CHAR RECORDS"
            #INSERT NEW CHAR RECORDS        
            separated_char_ids = []
            for character in characters:
                separated_char_ids.append(sync_test_subject_a_pool.create({'name':character}).id)

            self.lock = True

            print "UPDATE self.separated_chars WITH CHAR IDS"
            #UPDATE self.separated_chars WITH CHAR IDS
            self.separated_chars = separated_char_ids

            self.lock = False
            print "CHAR SEPARATION END"

sync_test_subject_b()

If anybody knows a better solution, feel free to post it in this thread.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!