Odoo extension and inheritance

amchugh89 picture amchugh89 · Jul 14, 2016 · Viewed 8.5k times · Source

Odoo has three types of inheritance, and I have at least that number of questions.

1. 'Normal' Inheritance (_inherit)

This is relatively intuitive to me - but why don't they just do it in the pythonic way:

ChildClass(ParentClass):

Why do they have the (seemingly equivalent):

ChildClass(model.Model):
     _inherit = 'module.parentclass'

2. Extension

This makes no sense to me (in that I don't know why you would use it), an example is below, but can anyone give me a practical use case. http://www.odoo.com/documentation/9.0/reference/orm.html#extension

3. Delegating (_inherits)

This doesn't really make sense to me either, it seems like a multiple subclassing but of just fields, not methods.

QUESTION

  1. Why does _inherit exist, what benefits/differences over normal subclassing?

  2. When/why would you extend? I think I have an idea, but I'm sure someone else can express clearer.

  3. Maybe a little what,why about _inherits

Answer

amchugh89 picture amchugh89 · Jul 14, 2016

I have been just messing around with the inheritance myself, below are examples of odoo 'classical' inheritance (pass _inherit and _name to child) and odoo 'extension,' only pass _inherit to child

_inherits (delegation) is so wacky I'm not even going to test it out. I don't see how I would ever use it - the docs explain the how (http://www.odoo.com/documentation/9.0/reference/orm.html#delegation) if anyone could explain the why that would be nice but I'm not going to keep stressing it.

MODELS

class Parent(models.Model):
    _name = 'aidentest.parent'

    first = fields.Char()
    last = fields.Char()

    def call(self):
        return self.check(self.first)

    def check(self, s):
        return "name: {} familia: {}".format(s, self.last)

#normal inheritance of parent
class Child1(models.Model):
    _name = 'aidentest.child1'
    _inherit = 'aidentest.parent'

    first = fields.Char()

    def call(self):
        return self.check(self.first)


#this extends parent
class Child2(models.Model):
    #_name = 'aidentest.child2' #no name - "extension" of inherited model
    _inherit = 'aidentest.parent'

    middle = fields.Char()

    def call(self):
        return self.check(self.first)

CONSOLE

>>> p1 = self.env['aidentest.parent'].create({'first':'mr','last':'dad'})
>>> p1.read()
[{'create_uid': (1, u'Administrator'), 'create_date': '2016-07-14 13:54:23', 'display_name': u'aidentest.parent,3', '__last_update': '2016-07-14 13:54:23', 'write_uid': (1, u'Administrator'), 'middle': False, 'write_date': '2016-07-14 13:54:23', 'last': u'dad', 'id': 3, 'first': u'mr'}]
>>> p1.call()
'name: mr familia: dad'
>>> p1.middle
False  

False means the field is there (via the 'extension' of Child2, but it is not populated) otherwise I would have gotten an Attribute Error

>>> c1 = self.env['aidentest.child1'].create({})
>>> c1.first
False
>>> c1.middle  
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'aidentest.child1' object has no attribute 'middle' 

Child1 inherits from the base class only, not from the 'extended' base class - it ignores Child2's extension of parent. Child2 extended parent by adding 'middle' field, Child1 has no access to that field

>>> c2 = self.env['aidentest.child2'].create({})
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\mamwo\Desktop\odoo\openerp\api.py", line 768, in __getitem__
    return self.registry[model_name]._browse(self, ())
  File "C:\Users\mamwo\Desktop\odoo\openerp\modules\registry.py", line 84, in __getitem__
    return self.models[model_name]
KeyError: 'aidentest.child2'

The Extending model doesn't really exist (has no name and you can not instantiate it), it just adds stuff to the parent.