有3个类, sync.test.subject.a
与 sync.test.subject.b
有很多关系,由 sync.test.subject.c
继承 .
sync.test.subject.b
的 separated_chars
字段通过名为 _compute_separated_chars
的计算函数填充,该函数由 sync.test.subject.b
的 chars
字段的更改触发 .
sync.test.subject.c
的作用基本上是通过自己的 name
设置 chars
,以便触发 _compute_separated_chars
.
问题是我无法从计算函数内部删除与Many2many字段(即 sync.test.subject.a
剩余记录)相关的剩余记录,因为在执行该函数之前,该字段已被系统清空,因此我甚至可以使用临时用于存储 sync.test.subject.a
ids的字段,因为任何与 separated_chars
无关的更改都会被提交't be committed by the system from inside the compute function (By any changes, I mean really ANY changes either to other fields from the same model or other changes to other models won't . 我该如何解决这个问题?
楷模:
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.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()
#DELETE LEFTOVER RECORDS FROM a_model
for character in self.chars:
self.separated_chars += a_model.create({'name': character})
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()
浏览次数:
<?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>
我认为这种行为是由Odoo实现的懒惰实现来处理链计算字段触发器而不是正确处理触发器(依次依赖于依赖关系)它们只是更新每个计算字段每次都有变化到每个其他字段 . 因此,它们限制对计算功能内部任何其他字段的任何更新 . 因为如果他们不这样做,它会破坏递归计算函数调用 .
1 回答
因为这个问题很有意思并且处理了新的Odoo API的行为,所以我花了一些时间来使用
compute
方法 . 你在问题中所说的并不是完全错误的,尽管有几个过早的陈述 .为了演示Odoo的行为,我使用以下设计创建了简单的Books应用程序 .
有两种型号 - 'books.book'和'books.author' . 他们每个人都与另一个人有一种关系 - 这种模式比正常模式,因为每本书都可能由一位或多位作者撰写,每位作者都应该写一本或多本书 .
这里有一个地方可以说是有点需要处理来自这种
compute
方法的Many2many
相关对象 . 那是因为Many2many
记录存在并且彼此独立地拥有一个生命 . 与One2many
关系它有很大的不同 .但无论如何,为了重现您在示例中向我们展示的行为,我计算了
author.books
字段 - 它的值是由_get_books()
方法计算的author
类 .为了表明不同的计算字段能够很好地独立工作,我创建了另一个计算字段 -
name
,它是author
类的方法_get_full_name()
.现在关于
_get_books()
方法的一些话 . 基于books_list
文本字段,此方法为books_list
的每一行生成一本书 .创建图书时,方法首先验证是否已存在具有此名称的图书 . 如果是这种情况,本书与作者相关联 . 否则,会创建一本新书并将其链接到作者 .
现在,你最感兴趣的问题是 - 在新书出版之前,与这位作者有关的现有书籍是 deleted . 为此,该方法使用 low level SQL queries . 这样我们就可以处理
compute
方法中没有相关对象列表的问题 .处理依赖于其他字段的计算字段时必须考虑的因素如下:
当他们所依赖的字段发生变化时计算它们(这是好消息)
每次尝试访问它们的值时,都会评估重新计算它们的需要 . 因此需要注意避免无休止的递归 .
关于更改compute方法中其他字段的值 . 阅读documentation的以下部分:
这也适用于
compute
方法 . 那意味着什么?这意味着如果将值分配给模型的另一个字段,则该值将不会写入数据库中 . 但是值将返回到用户界面并在保存表单时写入数据库 .在粘贴我的示例代码之前,我建议您再次更改应用程序的设计,而不是以这种方式处理来自compute方法内部的many2many关系 . 创建新对象效果很好,但删除和修改现有对象很棘手而且一点也不愉快 .
这是
books.py
文件:和用户界面:
编辑
例如,如果要将作者类子类化,则从Many2many字段定义中删除
relation
,column1
和column2
属性 . 他将保留默认的关系表名称 .现在,您可以在每个子类中定义一个这样的方法:
如果要从此关系表中删除记录,请在SQL查询构造中使用此方法 .