Using Abstract Models for reusable Model features

Sometimes, there is a particular feature that we want to be able to add to several different models. Repeating the same code in different files is bad programming practice, so it would be nice to be able to implement it once and be able to reuse it many times.

Abstract models allow us to just create a generic model that implements some feature that can then be inherited by regular models in order to make that feature available in them.

As an example, we will implement a simple Archive feature. It adds the active field to the model (if it doesn't exist already) and makes available an archive method to toggle the active flag. This works because active is a magic field; if present in a model by default, the records with active=False will be filtered out from queries.

We will then add it to the Library Book model.

Getting ready

We will reuse the my_module addon module from Chapter 3, Creating Odoo Modules.

How to do it…

The archive feature would certainly deserve its own addon module, or at least its own Python code file. But to keep the explanation as simple as possible, we will cram it into the models/library_book.py file:

  1. Add the abstract model for the archive feature. It must be defined in the Library Book model, where it will be used:
    class BaseArchive(models.AbstractModel):
        _name = 'base.archive'
        active = fields.Boolean(default=True)
    
        def do_archive(self):
            for record in self:
                record.active = not record.active
  2. Now, we will edit the Library Book model to inherit the Archive model:
    class LibraryBook(models.Model):
        _name = 'library.book'
        _inherit = ['base.archive']
        # ...

An upgrade to the addon module is needed for the changes to be activated.

How it works…

An Abstract model is created by a class based on models.AbstractModel instead of the usual models.Model. It has all the attributes and capabilities of regular models; the difference is that the ORM will not create an actual representation for it in the database. So, it can have no data stored in it. It serves only as a template for a reusable feature that is to be added to regular models.

Our Archive abstract model is quite simple; it just adds the active field and a method to toggle the value of the active flag, which we expect to later be used via a button on the user interface.

When a model class is defined with the _inherit attribute, it inherits the attribute methods of those classes, and what is defined in our class adds modifications to these inherited features.

The mechanism at play here is the same as that for a regular model extension (as per the Add features to a Model using inheritance recipe). You may have noticed that here, _inherit uses a list of model identifiers instead of a string with one model identifier. In fact, _inherit can have both forms. Using the list form allows us to inherit from multiple (usually Abstract) classes. In this case, we are inheriting just one, so a text string would be fine. A list was used instead to underline that a list can be used.

There's more…

A noteworthy built-in abstract model is ir.needaction_mixin. It allows for records to signal that a user action is needed on them and is widely used together with the Social Network messaging features.

Another widely used abstract model is mail.thread, provided by the mail (Discuss) addon module. It enables, on models, the message features that power the message wall seen at the bottom of many forms.

Other than AbstractModel, a third model type is available: models.TransientModel.

It has database representation like models.Model, but the records created there are supposed to be temporary and regularly purged by a server-scheduled job. Other than that, Transient models work just like regular models.

They are useful for more complex user interactions known as wizards, for example, to request the user some input to then run a process or a report. In Chapter 6, Advanced Server Side Development Techniques, we explore how to use them for advanced user interaction.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.32.230