【问题标题】:Odoo : Computed fields, don't update in some case?Odoo:计算字段,在某些情况下不更新?
【发布时间】:2016-05-23 10:46:35
【问题描述】:

我有一个计算字段,在更新字段时必须更新它。 所以我使用@api.depends('field1')并链接函数

field_to_compute: fields.integer(compute='the_function' store=True)

效果很好。

但是知道我想在field1 取值A 时更新它,并在field1 取值B 时保持不变。但是 field_to_compute 的旧值是从数据库中导入的,并未计算出来。

所以我有两个问题:

  • 如何让用户自己设置值。 (我可以修改它, 但是当我创建一个新成员时,它将被计算并且仅在之后 第一次保存我可以在 UI 中修改)
  • 我怎样才能做出类似的东西:

    @api.depends('field1')
    def the_function(self): 
         value = self.field1
         if value == A:
             field_to_compute = 123123
         elif value == B: 
             field_to_compute = stored_field_to_compute #field_to_compute
    

    保持与之前存储的值相同

编辑(示例):

我在当前模型的一个 res.partner 中,继承了 res.partner。 我有一个字段:

'model_state': field.char(compute='compute_type', string = 'Demand', store=True, readonly=True)

在另一个继承 res.partner 的 res.partner 中,在另一个模块中,我有 2 个字段:grade 和 status,分别是一个 int 和一个 many2one。计算与 model_state 相同的 compute_type,方法相同。

我也在这个 res.partner 中,有一个 one2many 字段:link_ids

所以我的功能是:

@api.depends('link_ids.type', 'link_ids.result')
def compute_type(self):
    for record in self:
       if self.link_ids:
           if self.link_ids.result == 'A':
               if self.link_ids.type == 'type1':
                   record.model_state = 'Mytext'
                   record.grade = 15
                   record.state = 1 #this is an id
               elif self.link_ids.result == 'B':
                   record.model_state = 'MySecondText'
                   record.state = 2 #this is an id

我不会把所有的东西都放上去,因为它就像 25 elif (不是所有都一样,如果等等等等),所以它不会是相关的。我检查了很多时间是否没有修改记录。等级如果没有对其进行任何操作,否则或不知道,但它只是被清空。

基本上,简化后,如果投票结果“OK”,我想做点什么。并将状态的id更改为“接受”,给一个文本(如标题),并给他一个更好的成绩,如果不是,他有一个状态的id为“拒绝”,给另一个文本,然后保持与实际成绩相同。

【问题讨论】:

  • 你怎么能猜到 self.link_ids.result 这样的 one2many 的结果?其中 link_ids 可能包含多条记录,因此可能有多个结果。并希望这里的代码没有错误是错字取决于实际上是@api.depends(...)
  • 主键,对一个 res_partner 只能提出一个需求。这只是为了在树视图中访问我的 res_partner 并选择其中一个(我在可编辑的树视图中)。所以,当我在 res_partner 中询问 links_ids 时,它会找到他所在的元组并查看值。我尝试了很多,它总是能达到我的预期,除了不能改变的字段(我需要在我的模型中选择一个 res.partner,many2one 视图对此非常有用)
  • 关于错字,我加了's',只是我的帖子中的错字,不是代码中的错字
  • 如果我没记错的话,self.link_ids.field_x == 'foobar' 比较会给你一个单例错误,在 link_ids 中有多个条目。
  • 是的,但它应该是,每个 res_partner 应该只有一个 link_id。最后,客户改变了主意,关于如何建立一对一关系的任何想法? (为了不再有单例错误),如果我在 many2one 中更改我的 link_ids,我将在 res_partner 中有一个 many2one,在我的模型中有一个 many2one。这行得通吗?

标签: python python-2.7 openerp odoo-8


【解决方案1】:

自己进行预取(field_to_compute 必须存储):

@api.multi
@api.depends('field_x')
def _compute_field_to_compute(self):
    # prefetch
    data = {d['id']: d['field_to_compute']
            for d in self.read(['field_to_compute'])}
    for record in self:
        if record.field_x == '123456':
            record.field_to_compute = '654321'
        else:
            record.field_to_compute = data.get(record.id, 'default')

【讨论】:

  • 非常感谢,我会尽快尝试!即使在我删除需求之后,这是否会保持我的 res_partner 计算字段? (@api.depends 指的是需求字段,计算字段在 res_partner 中,所以当我删除需求时,每个计算字段都被删除。
  • 我收到此错误,对于 record._origin record.origin 和 self._origin record.freemason_grade = record._origin.freemason_grade AttributeError: 'res.partner' object has no attribute '_origin' (在odoo 8)关于第二个选项,我需要存储两个不同的字段,例如,我只需将第二个字段的 d['id'] 更改为 d['di'] ?
  • 我将编辑我的 anwser。 _origin 解决方案只能在 onchanges 中使用。对于您的第二个问题:您可以只使用字典中的字典。只需将d['field_to_compute'] 替换为{'stored_field_1':d['stored_field_1'], 'stored_field_2': d['stored_field_2']} 并像record.stored_field_1 = data.get(record.id, {}).get('stored_field_1', 'default') 一样使用它
  • 谢谢,data 内部的 for 会是 {'stored_field_1', 'stored_field_2'} 吗?
  • 谢谢它的工作,正好赶上演示!非常感谢
【解决方案2】:

如果值为 B,则不要执行任何操作...或者更好:仅在需要时设置字段值。比如:

def _compute_foo(self):
    for item in self:
        if item.other_field != B:
             item.foo = 'newvalue'

我认为你的问题是你没有像计算字段那样设置值(参见item.foo = 'newvalue')。

看看official docs。

【讨论】:

  • 当我没有为该字段设置任何值时,它变为空(NULL)编辑:我认为它无论如何都会尝试计算,因为它是一个计算字段,但它看不到任何值,所以它根本不输入任何值..即使它是 store=True
【解决方案3】:

你应该尝试关注,

@api.onchange('field1')
def function(self):
    field_value = self.field_to_compute
    if self.field1 == A:
        field_value = 123123
    self.field_to_compute = field_value

【讨论】:

  • 我刚试过,如果值为A,它会工作,它会给出123123。但如果值为B,它仍然是空的,即使它不是。但我使用的是 api.depends,因为我修改了来自 2 个不同模块的值。它接缝的是,当它调用计算时,它首先清空将被计算的字段,然后运行该函数。也许我必须创建一个字段来存储字段的实际状态
  • 准确地说,我用phppgadmin检查了数据库中修改前后的结果,修改后为NULL。
  • 你能告诉我你想达到什么目标吗?以示例数据为目标?
  • 我进行了编辑,以便您可以清楚地看到它。感谢您花时间解决我的问题!
【解决方案4】:

尝试:

@api.onchange('field1')
def function(self)
     if value == A:
         field_to_compute = 123123
     elif value == B: 
         field_to_compute = stored_field_to_compute #field_to_compute keep the same value as the one stored before

【讨论】:

    【解决方案5】:

    对于需要将其值保存在数据库表中的计算字段,我们使用“@api..depends('field_attributes')”装饰器,当定义的字段属性发生更改时,它会触发执行函数。

    对于不需要在数据库表中保存其值的计算字段,我们不再需要这个“@api..depends('field_attributes')”,重新加载表单将作为触发函数的执行。但这样做的缺点是,我们将无法从该特定字段中搜索数据。

    【讨论】:

      猜你喜欢
      • 2020-05-04
      • 2018-03-14
      • 2017-06-21
      • 2022-06-19
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-11
      相关资源
      最近更新 更多