With relational fields, we need to decide beforehand the relation's target model (or comodel). But sometimes, we may need to leave that decision to the user and first choose the model we want and then the record we want to link to.
With Odoo, this can be achieved using Reference fields.
We will reuse the my_module
addon module from Chapter 3, Creating Odoo Modules.
Edit the
models/library_book.py
file to add the new related field:
from openerp import models, fields, api class LibraryBook(models.Model): # … @api.model def _referencable_models(self): models = self.env['res.request.link'].search([]) return [(x.object, x.name) for x in models]
ref_doc_id = fields.Reference( selection='_referencable_models', string='Reference Document')
Since we are changing the model's structure, a module upgrade is needed to activate these changes.
Reference fields are similar to many-to-one fields, except that they allow the user to select the model to link to.
The target model is selectable from a list provided by the selection
attribute. The selection
attribute must be a list of two element tuples, where the first is the model internal identifier, and the second is a text description for it.
Here is an example:
[('res.users', 'User'), ('res.partner', 'Partner')]
However, rather than providing a fixed list, we can use a model list configurable by end users. That is the purpose of the built-in Referenceable Models available in the Settings | Technical | Database Structure menu option. This model's internal identifier is res.request.link
.
Our recipe started with providing a function to browse all the Model records that can be referenced to dynamically build a list to be provided to the selection
attribute. Although both forms are allowed, we declared the function name inside quotes, instead of a direct reference to the function without quotes. This is more flexible, and for example, allows for the referenced function to be defined only later in the code, which is something that is not possible when using a direct reference.
The function needs the @api.model
decorator because it operates on the model level, not on the recordset level.
While this feature looks nice, it comes with a significant execution overhead. Displaying the reference fields for a large number of records, for instance, in a list view, can create heavy database loads as each value has to be looked up in a separate query. It is also unable to take advantage of database referential integrity like regular relation fields can.