Odoo Help


How to get a virtual recordset from an ordinary recordset?

on 11/25/16, 9:20 AM 1,318 views

As described here onchange methods are called with virtual recordset by Odoo, if a corresponding field is changed. Say I have the following onchange method:

def onchange_my_field(self):

when Odoo calls this method internally, the "self" is a virtual recordset. However, I have a scenario where I would like to call this method manually, from the another object method, where I do NOT have virtual recordset, but a normal recordset instead, so if I call the onchange method like this:


it gets called with ordinary recordset instead of virtual recordset (consequently the final result is as expected, except of huge difference in performance).

In order to avoid the performance penalty, I would like to get somehow virtual recordset from the ordinary "self" recordset I have for the moment and than call the onchange function using it. i.e. something like:

rec = get virtual recordset from self

it comes down to the question: How to get a virtual record/recordset from an ordinary record/recordset?


Axel Mendoza

--Axel Mendoza--
| 7 8 8
Camaguey, Cuba
--Axel Mendoza--

DevOps - Full stack - Software Architect - Developer - Technology Integrator

I could help you to develop anything and solve complex problems based on technologies, integrations and tricky stuffs mostly in Python with OpenERP/Odoo, Zato, Django and many others frameworks programming languages and technologies.

I offers consulting services to anyone with an unanswered questions or needs for customizations. Think about it, maybe it's better to have an expert to solve your issues and projects than having a full-time employee trying to understand what to do and how

Reach me at aekroft@gmail.com

Axel Mendoza
On 11/27/16, 7:26 AM

Hi Temur

You could do it using the "new" method like this:

invoice_id = self.env['account.invoice'].new(vals)
invoice_vals = invoice_id._convert_to_write(invoice_id._cache)

Where vals is a normal dict of vals for the virtual record and invoice_vals will have the resulting virtual record modifications made by the onchange call. If you don't have the vals and you need to pass all the vals from a record you could use the method copy_data to get it by it's id like:

#from a recordset one record
vals = self.copy_data()
#from a record by id
vals = self.browse(id).copy_data()

also the copy_data method accept an optional dict argument with the default data for the result dict

UPDATE (Temur):

before calling "new" method,

if type(vals) == list:
vals = vals[0]

-see comment below.

Thanks Axel for your reply. I tried it and a code "vals = self.copy_data()" followed by "self.env['some.model'].new(vals)" gave me an error. I'll investigate the error deeper as soon as I'll have some spare time. I forgot to mention in my question that server used is a v9, should it work in v9 as well? Or you were referring to a different version?

on 12/2/16, 8:47 AM

That is the way of the new api, no matter what version you are using, v8, v9, v10 or master.

Axel Mendoza
on 12/2/16, 2:00 PM

It seems `new` method expects a dictionary, whereas `copy_data` method returns a list of dictionaries. I fixed the error by using `vals = self.copy_data()[0]` instead of `vals = self.copy_data()` and so I was able to get a virtual record.

on 12/6/16, 3:13 AM


Axel Mendoza
on 12/6/16, 3:41 AM

About This Community

This platform is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.


Odoo Training Center

Access to our E-learning platform and experience all Odoo Apps through learning videos, exercises and Quizz.

Test it now

Question tools

2 follower(s)


Asked: 11/25/16, 9:20 AM
Seen: 1318 times
Last updated: 12/6/16, 3:17 AM