2
votes

I have a computed field, that has to be updated when a field is updated. So I use @api.depends('field1') and link the function

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

It works fine.

But know I'd like to update it when field1 take value A and to remain the same when field1 take the value B. But the old value of field_to_compute was imported from a database and wasn't computed.

So I have two problems:

  • How can I allow the user to set the value himself. (I can modify it, but when I create a new member, it will be computed and only after the first save I can modify it in UI)
  • How can I make something like:

    @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
    

    keep the same value as the one stored before

EDIT (example):

I'm in a res.partner in the current model, inheriting of res.partner. I've a field in it :

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

In a second res.partner inheriting of res.partner too, in an other module, I have 2 fields : grade and status, respectively an int, and a many2one. Computing the same compute_type as model_state, the same way.

I also in this res.partner, have a one2many field : link_ids

So my function is :

@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

I won't put everything because it's like 25 elif (not all about the same if etc etc) so it wouldn't be pertinent. I checked a lot of time if nothing was modifying record.grade if nothing is done on it, in else or dunno, but it's just being emptied.

Basically, simplified, I'd like to do something if the result is "OK" to a vote. And change the id of the state to "accepted", give a text (like a title), and give him a better grade, and if it's not, he have an id of the state "denied", give an other text, and keep the same grade as he has actually.

5
How can you guess self.link_ids.result the result from one2many like this ? where as link_ids may contains multiple records so there may be multiple results. And hope there is no mistake in code here is typo in depends actually it's @api.depends(...)Emipro Technologies Pvt. Ltd.
primary key, to one res_partner you can only make one demand. It's just in order to have acces to my res_partner in the tree view and select one of them (i'm in an editable tree view). So, when in res_partner I ask for links_ids, it will find the tuple where he is and look at the values. I tried a lot and it always did what I expected, except for the field which must not change (I needed to select one res.partner in my model and the many2one view is pretty usefull for that)T.Nel
About the typo, I added the 's', it only was a typo in my post, not in the codeT.Nel
if i'm not wrong the self.link_ids.field_x == 'foobar' comparisons will give you a singleton error with more than one entry in link_ids.CZoellner
Yes it does, but it was supposed to, it was supposed to be only one link_ids per res_partner. Finally, client changed his mind, any idea about how to make a one2one relation? (In order to have no singleton error anymore), if I change my link_ids in a many2one, i'll have a many2one in res_partner, and a many2one in my model. Will this work?T.Nel

5 Answers

4
votes

Do a prefetch by yourself (field_to_compute has to be stored):

@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')
1
votes

if the value is B just don't do anything... or better: set the field value only when needed. Something like:

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

I think you problem is that you are not setting the value as you should do for computed fields (see item.foo = 'newvalue').

Take a look at official docs.

1
votes

You should try following,

@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
0
votes

Try with:

@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
0
votes

For the computed fields that needs to save its value on DB table, we use the "@api..depends('field_attributes')" decorator, that when there were a change made to the defined fields attributes, it will trigger to execute the Function.

For the computed fields that don't need to have saved its value on DB table, we do not need anymore this "@api..depends('field_attributes')", Reloading the form would serve as a trigger for the function's execution. But the disadvantage for this is, we won't be able to search a data from this certain field.