We have seen the basic in place extension of models, which is also the most frequent use of inheritance. But inheritance using the _inherit
attribute has more powerful capabilities, such as mixin classes.
We also have available the delegation inheritance method, using the _inherits
attribute. It allows for a model to contain other models in a transparent way for the observer, while behind the scenes each model is handling its own data.
Let's explore these possibilities in more detail.
The method we used before to extend a model used just the _inherit
attribute. We defined a class inheriting the todo.task
model, and added some features to it. The class _name
was not explicitly set; implicitly it was todo.task
also.
But using the _name
attribute allows us to create mixin classes, by setting it to the model we want to extend. Here is an example:
from openerp import models class TodoTask(models.Model): _name = 'todo.task' _inherit = 'mail.thread'
This extends the todo.task
model by copying to it the features of the mail.thread
model. The mail.thread
model implements the Odoo messages and followers features, and is reusable, so that it's easy to add those features to any model.
Copying means that the inherited methods and fields will also be available in the inheriting model. For fields this means that they will be also created and stored in the target model's database tables. The data records of the original (inherited) and the new (inheriting) models are kept unrelated. Only the definitions are shared.
These mixins are mostly used with abstract models, such as the mail.thread
used in the example. Abstract models are just like regular models except that no database representation is created for them. They act like templates, describing fields and logic to be reused in regular models. The fields they define will only be created on those regular models inheriting from them. In a moment we will discuss in detail how to use this to add mail.thread
and its social networking features to our module. In practice when using mixins we rarely inherit from regular models, because this causes duplication of the same data structures.
Odoo provides the delegation inheritance mechanism, which avoids data structure duplication, so it is usually preferred when inheriting from regular models. Let's look at it in more detail.
Delegation inheritance is the less frequently used model extension method, but it can provide very convenient solutions. It is used through the _inherits
attribute (note the additional -s) with a dictionary mapping inherited models with fields linking to them.
A good example of this is the standard Users model, res.users
, that has a Partner model embedded in it:
from openerp import models, fields class User(models.Model): _name = 'res.users' _inherits = {'res.partner': 'partner_id'} partner_id = fields.Many2one('res.partner')
With delegation inheritance the model res.users
embeds the inherited model res.partner
, so that when a new User
is created, a partner is also created and a reference to it is kept in the partner_id
field of the User
. It is similar to the polymorphism concept in object oriented programming.
All fields of the inherited model, Partner, are available as if they were User fields, through the delegation mechanism. For example, the partner name
and address
fields are exposed as User fields, but in fact they are being stored in the linked Partner model, and no data structure duplication occurs.
The advantage of this, compared to prototype inheritance, is that there is no need to repeat data structures in many tables, such as addresses. Any new model that needs to include an address can delegate that to an embedded Partner model. And if modifications are introduced in the partner address fields or validations, these are immediately available to all the models embedding it!