Python Odoo 计算域:在没有 store=True 的情况下工作,在 store=True 的情况下不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31945069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:46:39  来源:igfitidea点击:

Odoo computed fields: works without store=True, doesn't work with store=True

pythonfieldodoo

提问by RobbeM

I have a computed field in Odoo with a function. Everything works fine when I don't add the store argument. When I add the store argument, it doesn't execute the code at all.

我在 Odoo 中有一个带有函数的计算域。当我不添加 store 参数时,一切正常。当我添加 store 参数时,它根本不执行代码。

My code:

我的代码:

class opc_actuelewaardentags(models.Model):
    _name = 'opc_actuelewaardentags'

    unit = fields.Char(compute='changeunit')

    def changeunit(self):
        print "print"
        allrecords_actwaardent = self.search([])

        obj_taginst = self.env['opc_taginstellingen']
        allrecords_taginst = obj_taginst.search([])


        for i in allrecords_actwaardent:
            for j in allrecords_taginst:
                if i.tagnaam == j.tagnaam and i.unit != j.unit:
                    i.unit = j.unit

So: when I call the code like this:

所以:当我这样调用代码时:

unit = fields.Char(compute='changeunit')

The code is executed (shows "print").

代码被执行(显示“打印”)。

When I call the code like this:

当我这样调用代码时:

unit = fields.Char(compute='changeunit', store=True)

The code is not executed (doesn't show "print").

代码未执行(不显示“打印”)。

Is there anything wrong in my code? Or is this a bug? It seems so strange to me...

我的代码有什么问题吗?或者这是一个错误?对我来说似乎很奇怪......

I need to be able to store the values in the database so I can filter on unit in the tree view.

我需要能够将值存储在数据库中,以便我可以在树视图中过滤单元。

edit:I applied Juan Salcedo's tip. Didn't work...

编辑:我应用了 Juan Salcedo 的提示。没用...

This is how I did it:

我是这样做的:

unit = fields.Char(default = changeunit)    

def changeunit(self):
    print "print"
    allrecords_actwaardent = self.search([])

    obj_taginst = self.env['opc_taginstellingen']
    #Hier dan i.p.v. self werken met dat obj_taginst
    allrecords_taginst = obj_taginst.search([])


for i in allrecords_actwaardent:
    for j in allrecords_taginst:
        if i.tagnaam == j.tagnaam and i.unit != j.unit:
            i.unit = j.unit
return i.unit

Gives error:

给出错误:

NameError: name 'changeunit' is not defined

NameError: 名称 'changeunit' 未定义

I also tried putting the unit field below def changeunit(self), but didn't work either.

我也尝试将 unit 字段放在 def changeunit(self) 下方,但也没有用。

回答by Sheliya Infotech

When we set store=Truethen we need to specify when we need to compute that function. Using @api.depends('fields')in that you specify field name when the change the value of the fields then compute method is call.

当我们设置store=True时,我们需要指定何时需要计算该函数。使用@api.depends('fields')在您指定的字段名称时更改的字段的值,然后计算方法是调用。

name = fields.Char('name')
length = fields.Integer(compute='get_length','Length',store=True)

@api.depends('name')
def get_length(self):
    self.length=len(name)

In this example when you change the name then get_lengthfunction is call.

在此示例中,当您更改名称时,则get_length调用函数。

回答by Emipro Technologies Pvt. Ltd.

Store=True without @api.depends means it will execute only once while the column/field is going to be created.

Store=True 没有@api.depends 意味着它只会在创建列/字段时执行一次。

so the effect you want to fire that method everytime will not be achieve with store=True without @api.depends or you need to remove store=True then it will calculate everytime when you access this field.

所以你想要每次触发该方法的效果将无法通过 store=True 实现而没有 @api.depends 或者你需要删除 store=True 那么它会在你每次访问这个字段时计算。

This are the changes you required to update in your code but before that you need to remove that column from database and after that restart server and upgrade module then it will come to there.

这是您需要在代码中更新的更改,但在此之前您需要从数据库中删除该列,然后重新启动服务器并升级模块,然后它将到达那里。

class opc_actuelewaardentags(models.Model):
    _name = 'opc_actuelewaardentags'

    unit = fields.Char(compute='changeunit')

    @api.multi
    def changeunit(self):
      print "print"  
        for obj in self:
            allrecords_actwaardent = self.search([])
            obj_taginst = self.env['opc_taginstellingen']
            allrecords_taginst = obj_taginst.search([])
            for i in allrecords_actwaardent:
                for j in allrecords_taginst:
                    if i.tagnaam == j.tagnaam and i.unit != j.unit:
                       obj.unit = j.unit
                       break

Another way: store = False never stored any value in database so if you want to store that value in database and don't won't to be updated (means it's fixed when create or update record) then you just need to override create/write method and inside update this field's value.

另一种方式:store = False 从来没有在数据库中存储任何值,所以如果你想将该值存储在数据库中并且不会被更新(意味着它在创建或更新记录时是固定的)那么你只需要覆盖 create/ write 方法并在内部更新此字段的值。

@api.model
def create(self, vals):
    vals.update({'field':value})
    return super(class_name,self).create(vals)

回答by Lo?c Faure-Lacroix

Here's a solution that might work for you, it's not perfect because it will could call the method often yet without real need most of the time.

这是一个可能对您有用的解决方案,它并不完美,因为它可以经常调用该方法,但大部分时间都没有真正的需要。

First add a new field that is computed.. Add that field to the UI where you need it and also hide it. It's not necessary to show it. You have to have it in the ui to force odoo to compute it.

首先添加一个新的计算字段。将该字段添加到您需要它的 UI 并隐藏它。没有必要展示它。您必须在 ui 中使用它才能强制 odoo 计算它。

When you compute the value of the field, also change the value of the field you really wanted to edit. Since a compute method can update multiple fields, it will work.

当您计算字段的值时,还要更改您真正想要编辑的字段的值。由于计算方法可以更新多个字段,因此它会起作用。

You don't have to make the original field as computed as far as I can say...

据我所知,您不必按照计算的方式计算原始字段...

But since you're modifying some fields using sql which isn't really good as you admitted yourself... Why don't you change that field with SQL at the same time? Make it easier on the Odoo side without hacks and make sure that your method that changes SQL kind of changes everything as it should. It's like you're editing one half of the problem and expecting odoo to catch data changes on itself. In order to achieve that, you'd need to have some way to have the database notify odoo that something changed... unfortunately, Postgresql doesn't do that so make sure that while you're updating something from SQL, that you have consistent data after doing your changes.

但是,既然您正在使用 sql 修改某些字段,这并不是您自己承认的那样好……为什么不同时使用 SQL 更改该字段?使 Odoo 方面更容易,无需黑客,并确保您更改 SQL 的方法按其应有的方式更改所有内容。这就像您正在编辑问题的一半,并期望 odoo 自己捕获数据更改。为了实现这一点,您需要有某种方法让数据库通知 odoo 某些事情发生了变化……不幸的是,Postgresql 不会这样做,因此请确保在您从 SQL 更新某些内容时,您有进行更改后保持一致的数据。

回答by fatema

i noticed this issue too, but in my case it was not necessary to store it in the database. so i kept it as store=false and the computed field worked and it has a value in the view and that's what mattered, only to have the values in the view..

我也注意到了这个问题,但就我而言,没有必要将其存储在数据库中。所以我将它保留为 store=false 并且计算字段有效并且它在视图中有一个值,这很重要,只有在视图中有值..

so when you set store=true, only new records will have a value in the computed field, while old data won't have values in the computed field

所以当你设置 store=true 时,只有新记录在计算域中有值,而旧数据在计算域中没有值

therefore you have to reset the values of the fields used in the computation of the field(depend fields)

因此,您必须重置用于计算字段(依赖字段)的字段的值

by writing a write statement inside the compute function, to reassign these fields their own values again, as if they are just created

通过在计算函数中编写一个 write 语句,再次为这些字段重新分配它们自己的值,就好像它们刚刚创建一样

for record in self.env['class'].search([]):
    record.field= record.field

record.field ->>> the fields used in field computation or api.depends(fields)

record.field ->>> 字段计算中使用的字段或 api.depends(fields)

回答by Charif DZ

This is not an issue, because Store = True (by the way it's recommended) tells odoo that when you compute the field store it's value to the database, so when you call this record next time the framework will retrieve the value from the database, and this value will be recomputed when any of the fields in the depends annotation is updated in the database or the UI.

这不是问题,因为 Store = True(顺便推荐)告诉 odoo,当您计算字段时,会将其值存储到数据库中,因此当您下次调用此记录时,框架将从数据库中检索该值,当依赖注释中的任何字段在数据库或 UI 中更新时,将重新计算此值。

so the code is not warking because when you specify the store = True after creating the value the value will be False and odoo will not recompute it until you change one of the fields that trigger the function.

所以代码没有警告,因为当您在创建值后指定 store = True 时,该值将为 False 并且 odoo 不会重新计算它,直到您更改触发该函数的字段之一。

you need to compute this field manually with a query to set the value for the existing records that you have in the database, don't worry about the new records odoo will compute and store the values.

您需要使用查询手动计算此字段以设置数据库中现有记录的值,不要担心新记录 odoo 会计算和存储这些值。

so store = True. means compute and store the value in the database and don't compute it again until one of the field is edited you need to compute the value for the existing records manually for the first time.

所以存储= True。意味着计算并将值存储在数据库中,并且在编辑字段之一之前不要再次计算它,您需要第一次手动计算现有记录的值。

回答by Manu W.

One way to achieve a computed field and the storage into the database is by adding an additional field that is relating to the computed field.

实现计算域并将其存储到数据库中的一种方法是添加与计算域相关的附加域。

field_name = fields.Monetary(string='Name', compute='_compute_anything')
field_name_store = fields.Monetary(related='field_name', string='Name', store=True)

@api.multi
def _compute_anything(self):
    variable = (field1+field2)
    update({'field_name':variable})