Wednesday, 17 January 2018

Inheritance in Models and Views

In Odoo/OpenERP we can inherit or use existing modules object/class/model and views. We can also inherit single field of existing modules. The question is why we need such inheritance.

The purpose of inheritance or why we need inheritance is given below:
  1. To change attributes of some fields which exists on existing/custom model (e.g. making fields readonly,invisible)
  2. To add/modify/delete old or new fields in existing/custom model (e.g. Product, Sales, HR, Fleet Management, Attendance modules model etc)
  3. We can also add buttons in already existing/custom model (form and tree) view by using inheritance
Before going directly into coding I want to tell you about inheritance.

What is Inheritance?

Inheritance means we are going to use or inherit old class/model, properties, methods and views in new class/model. This concept is related to Object Oriented Programming. In Odoo/ERP we extend properties, fields and views of an existing model in a modular way.

Inherit model or class

To inherit custom or existing models we use _inherit keyword.
class groups(models.Model):
 _inherit = 'res.groups'
 # we inherited res.groups model which is Odoo/OpenERP built in model and created two fields in that model.
 field_1 = fields.Char(required=True,string="Field One")
 field_2 = fields.Boolean(default=False,string="Field Two")       

Code Description

In above code snippet we have inherited res.groups model of Odoo, after inheritance we declare two fields the first one is of type Char and the second is Boolean type. This means that we are adding two fields in already create (res.groups) model/class by using inheritance. Now these two fields are also available in inherited model/class. Here we are define Char and Boolean type field you can define or add each type of field such as (Char, Integer, Float, Boolean, Many2many, Many2one, One2many, Date etc).
Now that we have inherited model/class of an existing model. Now we are going to inherit views.

Inherit Views

To inherit views (form and tree) of an existing model or class follow below steps.
  1. Create a new XML file in your_module >> views >> inherited_form_view.xml or inherited_tree_view.xml
  2. Use below code to inherit form and tree view
        <record model="ir.ui.view" id="res_group_form_view_inherited">
            <field name="name"></field>
            <field name="model">res.groups</field>
            <field name="inherit_id" ref="base.view_groups_form" />
            <!-- <field name="groups_id" eval="[(6, 0, [ref('obe_core.obe_coordinator')])]"/> -->
            <field name="priority" eval="15"/>
            <field name="arch" type="xml">

                <xpath expr="//field[@name='name']" position="after">
                    <field  name="field_1"/>
                <xpath expr="//field[@name='user_name']" position="after">
                    <field  name="field_2"/>


Code Description

In above code we have inherited res.groups form view. Here the main line is given below, its mean that we are going to inherit view_groups_form which is located in base module. Actually we are referencing here the parent or original form id of res.groups model named view_groups_form.

<field name="inherit_id" ref="base.view_groups_form" />      

Now that we have inherited parent form of res.groups model. Now we have to display fields that we have created in that model named field_1 and field_2. To display that fields we have used xpath expression. In "expr" attribute we used "//field[@name='name']" and "position="after"", its mean that place our newly created field after name field of parent form view. Position attribute have following values.

  1. position="after" : To display field after parent form view field mentioned in "expr"
  2. position="before" : To display field before parent form view field mentioned in "expr"
  3. position="inside" : To display field inside notebook of parent form view
  4. position="attributes" : To change field attribute such as read only and visibility of a field
  5. position="replace" : To replace parent form view field with your newly created field
In "expr" attribute you may use following values.

1-  expr="//div[@name='buttons']"

2-  expr="//group[@name='parent']"

3-  expr="."

4-  expr="//field[@name='target_move']"

5-  expr="//notebook/page[@string='Filters']"

6-  expr="//page[@name='filters']"

7-  expr="/form/notebook/page/field[@name='line_id']/tree/field[@name='analytic_account_id']"

8-  expr="/form/notebook/page/field[@name='line_id']

9-  expr="//page[@name='statement_line_ids']/field[@name='line_ids']/tree/field[@name='amount']"

10- expr="//button[@name='invoice_cancel']"

11- expr="//label[@for='module_account_followup']"

12- expr="/tree/field[@name='user_id']"      

Similarly if you want to display fields/tabs/pages,notebook etc in inherited form view use below code snippet.

 <xpath expr="//field[@name='name']" position="after">
  <field  name="field_1"/>

 <field name="template_id" position="attributes">
  <attribute name="attrs">{'required': 1}</attribute>

 <field name="field_id_which_you_want_to_replace" position="replace">
  <field name="field_id_which_you_want_to_display"/>

 <notebook position="inside">
  <page string="Overdue Payments" position="inside">
   <separator string="Overdue Payments Message"/>
   <field name="overdue_msg"/>

Similarly you can inherit tree view.

 <record id="res_group_tree_view_inherited" model="ir.ui.view">
  <field name="name"></field>
  <field name="model">res.groups</field>
  <field name="inherit_id" ref="hr.view_groups_tree"></field>
  <field name="arch" type="xml">

   <xpath expr="//field[@name='job_id']" position="after">
    <field name="employee_contracts"></field>
    <field name="state"></field>


  1. Hi I do these instructions but I get the following error

    Field 'field_1' dosn't exist

    Could you help me please

    1. Dear here "field_1" could be any of your field, which you have to override

  2. I have a question regarding view inheritance. I inherited a existing view and I want that view to use a new model. The new model is inherited from the model that is being used in that existing view. I keep getting error "widget is not a constructor" while performing this.

  3. i am getting the error that field doesnt exist.This happens only when i am trying to put a new field in the tree. Same field is working in the form but that field is not working in the tree view.. Please help

  4. I still don't understand about the expr syntax. When I tried to inherit a view and track a field to add another field after it I tried this expr:

    And it raised an error in upgrading the module. When my senior at work repair the code by changing it to:

    It worked. As I understand my code was similar to your 5th example above: expr="//notebook/page[@string='Filters']"
    Can you explain more for me in the path when to use double slash (//) when to use single slash (/)?