web-dev-qa-db-ja.com

Odoo計算フィールド:store = Trueなしでは機能し、store = Trueでは機能しません

Odooに関数付きの計算フィールドがあります。 store引数を追加しないと、すべて正常に機能します。 store引数を追加すると、コードがまったく実行されません。

私のコード:

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

だから:私がこのようなコードを呼び出すとき:

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

コードが実行されます(「印刷」が表示されます)。

このようなコードを呼び出すと:

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

コードは実行されません(「印刷」は表示されません)。

私のコードに何か問題がありますか?それともこれはバグですか?それは私にはとても奇妙に思えます...

ツリービューで単位をフィルタリングできるように、データベースに値を保存できる必要があります。

編集:フアンサルチェードのヒントを適用しました。動作しませんでした...

これは私がそれをした方法です:

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

エラーが発生します:

NameError:名前 'changeunit'が定義されていません

また、ユニットフィールドをdef changeunit(self)の下に配置しようとしましたが、どちらも機能しませんでした。

7
RobbeM

_store=True_を設定するときは、その関数をいつ計算する必要があるかを指定する必要があります。フィールドの値を変更するときにフィールド名を指定するという点で@api.depends('fields')を使用すると、computeメソッドが呼び出されます。

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

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

この例では、名前を変更すると、_get_length_関数が呼び出されます。

1

@ api.dependsなしのStore = Trueは、列/フィールドの作成中に1回だけ実行されることを意味します。

したがって、そのメソッドを毎回起動する効果は、@ api.dependsがないとstore = Trueで達成されないか、store = Trueを削除する必要があります。そうすると、このフィールドにアクセスするたびに計算されます。

これはコードで更新するために必要な変更ですが、その前にデータベースからその列を削除する必要があり、その後サーバーを再起動してモジュールをアップグレードすると、そこに到達します。

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

別の方法:store = Falseはデータベースに値を保存しないため、その値をデータベースに保存し、更新されない場合(つまり、レコードの作成または更新時に修正される)、create /をオーバーライドする必要があります。 writeメソッドと内部でこのフィールドの値を更新します。

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

計算フィールドとデータベースへのストレージを実現する1つの方法は、計算フィールドに関連するフィールドを追加することです。

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})
0
Manu W.

私もこの問題に気づきましたが、私の場合はデータベースに保存する必要はありませんでした。だから私はそれをstore = falseとして保持し、計算されたフィールドは機能し、ビューに値があり、それが重要でしたが、ビューに値があるだけでした。

したがって、store = trueを設定すると、新しいレコードのみが計算フィールドに値を持ち、古いデータは計算フィールドに値を持ちません。

したがって、フィールドの計算に使用されるフィールドの値をリセットする必要があります(フィールドに依存)

計算関数内に書き込みステートメントを記述して、これらのフィールドに、作成されたばかりのように、独自の値を再度割り当てます。

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

record.field->>>フィールド計算またはapi.depends(fields)で使用されるフィールド

0
fatema

これがあなたのために働くかもしれない解決策です、それはほとんどの場合実際の必要なしにまだ頻繁にメソッドを呼び出すことができるのでそれは完璧ではありません。

まず、計算される新しいフィールドを追加します。そのフィールドを必要なUIに追加し、非表示にします。表示する必要はありません。 odooに強制的に計算させるには、UIにそれを含める必要があります。

フィールドの値を計算するときは、本当に編集したいフィールドの値も変更してください。計算メソッドは複数のフィールドを更新できるため、機能します。

私が言うことができる限り、元のフィールドを計算されたものにする必要はありません...

しかし、SQLを使用して一部のフィールドを変更しているので、自分で認めたようにあまり良くありません...同時にSQLでそのフィールドを変更してみませんか? Odoo側でハッキングせずに簡単にし、SQLの種類を変更するメソッドがすべてを変更するようにします。問題の半分を編集していて、odooがそれ自体でデータの変更をキャッチすることを期待しているようなものです。これを実現するには、データベースに何かが変更されたことをodooに通知させる方法が必要です...残念ながら、Postgresqlはそれを行わないので、SQLから何かを更新しているときに、次のことを確認してください。変更を行った後の一貫したデータ。

0

これは問題ではありません。Store= True(推奨される方法)は、フィールドストアを計算するときにデータベースへの値であるとodooに通知するため、次にこのレコードを呼び出すときに、フレームワークがデータベースから値を取得します。この値は、dependsアノテーションのフィールドのいずれかがデータベースまたはUIで更新されたときに再計算されます。

したがって、値の作成後にstore = Trueを指定すると、値はFalseになり、関数をトリガーするフィールドの1つを変更するまで、odooは値を再計算しないため、コードは警告しません。

データベースにある既存のレコードの値を設定するには、クエリを使用してこのフィールドを手動で計算する必要があります。odooが値を計算して保存する新しいレコードについて心配する必要はありません。

したがって、store = Trueです。つまり、値を計算してデータベースに保存し、フィールドの1つが編集されるまで再計算しないでください。最初に、既存のレコードの値を手動で計算する必要があります。

0
Charif DZ