Skip to Content
Menu
This question has been flagged
1 Reply
8125 Views

It seem that api.one is deprecated in favor of api.multi + ensure.one

as an example:

  @api.one
  def _compute_total_cost(self):
        records = self.env["project.task"].search([("model", "in", self.ids)])       
        tcost = 0.0       
        for rec in records:           
            tcost += rec.cost       
        self.total_cost = tcost

 

  total_cost = fields.Monetary(comput="_compute_total_cost")


I tried to use api.multi but I am getting errors when there are more than one record in "records".

How would I switch to use api.multi in place of api.one in this case? Should I?

TIA

Avatar
Discard
Best Answer

Hi Yves,

The @api.one function is indeed being phased out in Odoo V12/V13. The reason behind this is that it was confusing and causing issues for multiple developers. You should now go with @api.multi. With @api.multi you can have multiple records though (for example when opening multiple records somewhere) so you should deal with this. Usually what you do is loop over all the records in the onchange function (so all records within self) and then do your computations on every record in the record set. An example:


@api.multi
def _compute_total_cost(self):
    for record in self:
        # Find all tasks for this record (which can be one record in a recordset)
        task_records = self.env["project.task"].search([("model", "in", record.ids)])
        tcost = 0.0
        # Loop over your tasks results
        for task in task_records:
            tcost += task.cost
        # Write the result for this record on this record
        record.total_cost = tcost

If you're sure that your function is always one record (and want to enforce it) you can also use the self.ensure_one(). The Odoo framework will make sure there is always just one record then. In this case your example would be:

@api.multi
def _compute_total_cost(self):
    self.ensure_one()      
    for rec in records:  
        task_records = self.env["project.task"].search([("model", "in", self.ids)])        
        tcost = 0.0       
        for task in task_records:
            tcost += task.cost
        record.total_cost = tcost

You can even remove the loop in a self.ensure_one and just work with self, as it should always be one record. I've coded it the same for transparancy about the difference in both functions.


For more information about @api.one and @api.multi see https://www.odoo.com/nl_NL/forum/help-1/question/difference-between-api-one-and-api-multi-in-api-odoo-openerp-68209 and https://www.odoo.com/documentation/12.0/reference/orm.html#recordsets

Regards,
Yenthe

Avatar
Discard
Related Posts Replies Views Activity
1
Jun 15
9576
1
Mar 22
30242
1
Feb 25
23603
2
Jul 22
3622
1
Sep 21
3143