How To Transfer Data From One Model To Another In Odoo
What Is ODOO ERP?
Odoo ERP envisions transforming the way a company runs its business. Odoo leverages open source technology making the business simpler and fully integrated. No matter what industry your company belongs to, Odoo ERP is constantly revolutionizing your company’s growth and improving revenue.
Odoo, Also known as Open ERP, was founded by Fabien Pinckaers in 2005. The word Odoo is the acronym for On-Demand Open Object. Odoo is a large collection of business-related applications and modules like CRM, Sales Management, E-Commerce, Warehouse Management, Purchase Management, Accounting Suit, Manufacturing Management, HRMS, etc.. All these basic modules are collectively called Enterprise Resource Planning software.
Also Read: Odoo ERP Review: An In-Depth Review of Its Features, Pros, and Cons
Odoo has more than 14,000 third-party Apps/Plugins available in its app store. Each of them is custom-built for different user needs. Today, Odoo is one of the most widely used Open-Source ERP Solutions in the market.
Data and Model
Odoo is greatly data-driven, and a big part of the module's definition is thus the definition of the various records it manages: UI (menus and views), security (access rights and access rules), reports, and plain data are all defined via records.
In Odoo, a model is a class that maps to the data relation (table) and potentially bridges tables (e.g. for many to many relations). It contains the essential fields and behaviors of the data you're storing. Generally, each model maps to a single database table, Data Transfer in Odoo.
Data Transfer In Odoo
In this blog, we are going to discuss how we can transfer data from one model to another in odoo.
We can mainly transfer one data from a model to another different model in four ways they are:-
(a) By using Context
(b) With the help of ORM Methods
(c) By Overriding Create Method
(d) By Overriding Write Method
Let us discuss more deeply
Content with Context
The context is a python dictionary and is used to pass certain data to a method. Since nearly all methods have a context parameter you can use the context to pass data through several levels of python methods.
You may want to pass some data to a specific page in Odoo, and change the fields based on those data. In those cases, you want to use Context.
Context is a data structure passed to the request object that contains hidden values and can be used to change the results of the page.
Context is a frozendict data type in Odoo. That’s why you can change it as you do in a dict data type, for example:
dict_object.update({ 'test': 'test_value', })
As the Context is frozendict, it won’t take such changes. Odoo provides a way to change values; it’s called ‘with_context’. The syntax is as follows:
self = self.with_context({ 'test': 'test_value', })
This one should rewrite the context available in the self-object by adding the new key: value pair you have mentioned. There are times, this might not work as expected, and you want a patching technique to update the context. This can be done by changing the data type to dict.
self.env.context = dict(self.env.context) self.env.context.update({ 'test': 'test_value', })
This would also add the new key: and value pair to your context and work as expected. There is almost no security concern here for converting the frozendict as the context will destroy once the page is left soon enough.
you can set a context value in an XML view and process it in the write() method of the osv object.
context.get('active_id',False)
Returns the value of the key 'active_id'. If the key is not in the context, then it returns the value 'False'.
The value in 'active_id' is passed from the web client and contains the ID of the currently selected record.
Here is an example of how the context is used in the Sale module. File sale_view.xml:
<record id="view_order_form" model="ir.ui.view"> <field name="name">sale.order.form</field> <field name="model">sale.order</field> <field name="arch" type="xml"> <form string="Sales Order" version="7.0"> <header> <button name="invoice_recreate" states="invoice_except" string="Recreate Invoice" groups="base.group_user"/> <button name="invoice_corrected" states="invoice_except" string="Ignore Exception" groups="base.group_user"/> <button name="action_quotation_send" string="Send by Email" type="object" states="draft" class="oe_highlight" groups="base.group_user"/> ....
You can see that the button third button (Send by Email) calls a method.
action_quotation_send in sale.py.
Here is the relevant code in sale.py:
def action_quotation_send(self, cr, uid, ids, context=None): ....... ctx.update({ 'default_model': 'sale.order', 'default_res_id': ids[0], 'default_use_template': bool(template_id), 'default_template_id': template_id, 'default_composition_mode': 'comment', 'mark_so_as_sent': True }) return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'mail.compose.message', 'views': [(compose_form_id, 'form')], 'view_id': compose_form_id, 'target': 'new', 'context': ctx, }
The context is updated with the flag mark_so_as_sent set to True. Afterward, the send-mail window (mail.compose.message) is opened and the modified context is passed.
Then the send_mail() method is overwritten. If the flag mark_so_as_sent has been set in the context, then the new functionality is called.
This ensures that the current behavior of send_mail() is not affected. But when the wizard is opened from the Sale Order, the new functionality will be executed.
Also in sale.py:
class mail_compose_message(osv.Model): _inherit = 'mail.compose.message' def send_mail(self, cr, uid, ids, context=None): context = context or {} if context.get('default_model') == 'sale.order' and context.get('default_res_id') and context.get('mark_so_as_sent'): context = dict(context, mail_post_autofollow=True) wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, 'sale.order', context['default_res_id'], 'quotation_sent', cr) return super(mail_compose_message, self).send_mail(cr, uid, ids, context=context)
With the Help of ORM Methods
So firstly, we can look at how to fetch data from a different model; for fetching data, we use ORM search and browse methods.
And we need to specify the model from which we are going to fetch data. If you want to filter the records based on some conditions, you can set the domain so we will get the results based on the conditions.
Here we have two sample classes; let us assume both have some fields also.
Class SampleOne(models.Model) _name=’sample.one’ sample_one=fields.Char(string=”name”) Class SampleTwo(models.Model) _name=’sample.two’
So if I need to get the values of first-class in the second one, we need to create a method in the second model; if you want to call the ORM method directly from an object, you can use self.env['obj'].method
Class SampleTwo(models.Model) _name=’sample.two’ def get_data(self): fetched_data=self.env.[‘sample.one’].search([]) return fetched_data
The self.env environment reference allows us to access any other model. Here we are assigning the searched results to a variable and returning it; we can specify from which model we need to fetch data inside that self.env.[‘obj.name’] and this function can be called as your wish it can be given as the action of any button also.
So if we need to give some conditions to filter our data you can set the domain inside the search as your wish.
Eg:
fetched_data=self.env.[‘sample.one’].search([('user_id', '=', self.user_id.id)])
We can also browse records for any model by using a browse method like this
self.env['model.name'].browse(ids)
We can also transfer or create data from the different models to a different destination model. So let us see how to do that,
Class SampleTwo(models.Model) _name=’sample.two’ def get_data(self): fetched_data=self.env.[‘sample.one’].create({ ‘ sample_one’:self.name, }) return fetched_data
Here inside the create you can specify to which field you are giving value and the corresponding value by
‘field_name’:’value’
We can also write data from one model to another like this,
self.env.[‘object.name’].write({ ‘ field_name’:’value’, })
By Overriding Create Method
Overriding existing functions in Odoo is quite easy to do. Odoo is built on Python, and Python allows you to use super calls, which makes it quite easy to override existing functions.
Also Read: Python for Beginners
We can Override the create function and change values on a record bypassing the value before storing it in the database.
The first thing is to inherit the model in which you are trying to create a record or pass value.
Let us take the model res.partners, for example,
from odoo import models, fields, api class res_partner(models.Model): _inherit = 'res.partner' Then, @api.model def create(self, values): """Override default Odoo create function and extend.""" # Do your custom logic here return super(ResPartner, self).create(values)
You can give values to create like,
record = self.env['your.model'].create({ 'name': 'Example' })
By Overriding Write Method
For Overriding write method also first inherit the model,
from odoo import models, fields, api class res_partner(models.Model): _inherit = 'res.partner' Then, @api.multi def write(self, values): """Override default Odoo write function and extend.""" # Do your custom logic here return super(ResPartner, self).write(values)
For giving values,
record_ids = self.env['your.model'].search([('name', '=', 'Example')]) for record in record_ids: record.write({ 'some_field': 'some_description' })
We hope this blog is helpful to you. Tell us in the comment section which method you’re currently using and why.
If you have any requirements related to Odoo ERP Development, Contact Our Developer team for assistance.
Expand Your Knowledge with Our Related Blogs
Get in touch with us!
Your email address will not be published.