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
Why does _inherit exist, what benefits/differences over normal subclassing?
When/why would you extend? I think I have an idea, but I'm sure someone else can express clearer.
Maybe a little what,why about _inherits
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.