计算方法被多次调用?

时间:2015-09-09 09:17:47

标签: python openerp odoo odoo-8 openerp-8

  

我发现这可能不是并发问题   方法被召回当我尝试更新sync.test.subject.b的{​​{1}} FIELD(在方法结束时)时。所以   我无法通过线程锁定来解决这个问题,因为该方法实际上等待自己再次调用。我不明白这是一种完全奇怪的行为。

我在更新计算字段时发现了一种奇怪的行为。在这种情况下,代码优于单词:

型号:

separated_chars

查看:

from openerp import models, fields, api, _

class sync_test_subject_a(models.Model):

    _name           = "sync.test.subject.a"

    name            = fields.Char('Name')

sync_test_subject_a()

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')

    @api.depends('chars')
    def _compute_separated_chars(self):
        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)

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

sync_test_subject_b()

class sync_test_subject_c(models.Model):

    _name           = "sync.test.subject.c"
    _inherit        = "sync.test.subject.b"

    name            = fields.Char('Name')

    @api.one
    def action_set_char(self):
        self.chars = self.name

sync_test_subject_c()

有3个类<?xml version="1.0" encoding="UTF-8"?> <openerp> <data> <!-- Top menu item --> <menuitem name="Testing Module" id="testing_module_menu" sequence="1"/> <menuitem id="sync_test_menu" name="Synchronization Test" parent="testing_module_menu" sequence="1"/> <!--Expense Preset View--> <record model="ir.ui.view" id="sync_test_subject_c_form_view"> <field name="name">sync.test.subject.c.form.view</field> <field name="model">sync.test.subject.c</field> <field name="type">form</field> <field name="arch" type="xml"> <form string="Sync Test" version="7.0"> <header> <div class="header_bar"> <button name="action_set_char" string="Set Name To Chars" type="object" class="oe_highlight"/> </div> </header> <sheet> <group> <field string="Name" name="name" class="oe_inline"/> <field string="Chars" name="chars" class="oe_inline"/> <field string="Separated Chars" name="separated_chars" class="oe_inline"/> </group> </sheet> </form> </field> </record> <record model="ir.ui.view" id="sync_test_subject_c_tree_view"> <field name="name">sync.test.subject.c.tree.view</field> <field name="model">sync.test.subject.c</field> <field name="type">tree</field> <field name="arch" type="xml"> <tree string="Class"> <field string="Name" name="name"/> </tree> </field> </record> <record model="ir.ui.view" id="sync_test_subject_c_search"> <field name="name">sync.test.subject.c.search</field> <field name="model">sync.test.subject.c</field> <field name="type">search</field> <field name="arch" type="xml"> <search string="Sync Test Search"> <field string="Name" name="name"/> </search> </field> </record> <record id="sync_test_subject_c_action" model="ir.actions.act_window"> <field name="name">Sync Test</field> <field name="res_model">sync.test.subject.c</field> <field name="view_type">form</field> <field name="domain">[]</field> <field name="context">{}</field> <field name="view_id" eval="sync_test_subject_c_tree_view"/> <field name="search_view_id" ref="sync_test_subject_c_search"/> <field name="target">current</field> <field name="help">Synchronization Test</field> </record> <menuitem action="sync_test_subject_c_action" icon="STOCK_JUSTIFY_FILL" sequence="1" id="sync_test_subject_c_action_menu" parent="testing_module.sync_test_menu" /> </data> </openerp> sync.test.subject.a有许多关系,由sync.test.subject.b继承。

sync.test.subject.c的{​​{1}}字段通过名为sync.test.subject.b的计算函数填充,该函数由separated_chars的{​​{1}}字段的更改触发。 / p>

_compute_separated_chars的作用基本上是通过自己的sync.test.subject.b设置chars,以便触发sync.test.subject.c

执行此操作会触发“错误”:

  • 创建新的chars输入名称,例如name
  • 保存新的_compute_separated_chars
  • sync.test.subject.c按钮
  • 致电ABCDEFG

您将看到该功能被触发两次。

以下是执行结果:

sync.test.subject.c

结果,只有action_set_char的记录加倍到Set Name To Chars。这是一种非常危险的行为,因为这会导致数据崩溃。

这是关于如何发生这种情况的详细步骤布局(基于打印输出):

CHAR SEPARATION BEGIN
SEPARATE CHARS
DELETE CURRENT CHARS
DELETE EXISTING sync_test_subject_a THAT ARE RELATED TO CURRENT SELF
INSERT NEW CHAR RECORDS
UPDATE self.separated_chars WITH CHAR IDS
CHAR SEPARATION BEGIN
SEPARATE CHARS
DELETE CURRENT CHARS
DELETE EXISTING sync_test_subject_a THAT ARE RELATED TO CURRENT SELF
INSERT NEW CHAR RECORDS
UPDATE self.separated_chars WITH CHAR IDS
CHAR SEPARATION END
CHAR SEPARATION END

问题:

  • 为什么A,B,C,D,E,F,G被叫两次 同一时刻?
  • 假定A,B,C,D,E,F,G,A,B,C,D,E,F,G的触发器 作为M1 = first call to the method M2 = second call to the method For example in this case chars = ABCDEFG > trigger the method M1 - CHAR SEPARATION BEGIN M1 - SEPARATE CHARS M1 tries to separate the chars into list [A,B,C,D,E,F,G] M1 - DELETE CURRENT CHARS This is needed to REPLACE current character records with the new ones. since the `separated_chars` is currently empty nothing will be deleted M1 - DELETE EXISTING sync_test_subject_a THAT ARE RELATED TO CURRENT SELF The method will try to get all of the `sync.test.subject.a` ids that is related to self by getting them from `separated_chars` so that they can be unlinked (This happens before M1 - DELETE CURRENT CHARS). Since nothing has been added to the `separated_chars`, this will not do anything M1 - INSERT NEW CHAR RECORDS Adding [A,B,C,D,E,F,G] `to sync.test.subject.a`, so `sync.test.subject.a` will have [A,B,C,D,E,F,G] M1 - UPDATE self.separated_chars WITH CHAR IDS CURRENTLY THIS IS NOT YET EXECUTED, so no `sync.test.subject.a` ids has been assigned to self. it will wait till M2 finish executing. M2 - CHAR SEPARATION BEGIN M2 - SEPARATE CHARS M1 tries to separate the chars into list [A,B,C,D,E,F,G] M2 - DELETE CURRENT CHARS Because the `separated_chars` IS STILL EMPTY nothing happens. M2 - DELETE EXISTING sync_test_subject_a THAT ARE RELATED TO CURRENT SELF See, currently the `separated_chars` field IS STILL EMPTY THOUGH the `sync.test.subject.a` is filled with [A,B,C,D,E,F,G] the method can't get the ids because the `separated_chars` is empty. M2 - INSERT NEW CHAR RECORDS Now the method adds [A,B,C,D,E,F,G] `to sync.test.subject.a`, so `sync.test.subject.a` will have [A,B,C,D,E,F,G,A,B,C,D,E,F,G] M2 - UPDATE self.separated_chars WITH CHAR IDS This will link `sync.test.subject.a` ids to self so now self has [A,B,C,D,E,F,G] M2 - CHAR SEPARATION END Now after this M1 will continue linking the `sync.test.subject.a` ids to self that means self will now have [A,B,C,D,E,F,G,A,B,C,D,E,F,G] M1 - CHAR SEPARATION END See the problem isn't how many times the method is executed but it's how the method calls itself when it tries to update the field. Which is nonsense. 的更新,_compute_separated_chars仅更新为ONCE,为什么 是两次调用的方法吗?

源文件:Source

0 个答案:

没有答案