Chapter 3 - Odoo 15 Development Book

Constraints

In any real business scenario, there is a chance that users may give incorrect data. By using Constraints, we can prevent users from entering incorrect data. Constraints are the restrictions that are set on a record to prevent incorrect data from being saved before the record is saved.

The two ways Python Constraints and SQL Constraints are two tools provided by Odoo for automatically verifying invariants.

SQL Constraints:

SQL Constraints are defined on the model using the class attribute _sql_constaints. This belongs to the part of PostgreSQL.

Syntax for writing SQL Constraints:

    _sql_constraints = [(name, sql_def, message)]

    name: SQL Constraints name.

    sql_def: PostgreSQL syntax of the constraint.

    message: error message.

For example:

sql_constraints = [('date_order_conditional_required', "CHECK( (state IN ('sale', 'done') AND date_order IS NOT NULL) OR state NOT IN ('sale', 'done') )", "A confirmed sales order requires a confirmation date."),]

It is the sql_constraits taken from the sale order. It aims to verify the confirmed sale order has a confirmation date. If it fails, it shows an error message. The SQL constraint in Python is defined before to the coding section; it is always specified in the field declaration section.

Python Constraints:

SQL constraints is an efficient way of guarantee data uniformity. In other circumstances, we may need to use more elaborate tests to assure data consistency. In such situations, we can use python constraints.

The Python constraint is a method, decorated with constrains(). It included on a record of the set. Decorator are used to specify which fields are involved in the constraints.These constraints are automatically evaluated when any of the fields are modified.

For example:

@api.constrains('product_id')
def check_product_is_not_kit(self):
   if self.env['mrp.bom'].search(['|', ('product_id', 'in', self.product_id.ids), '&', ('product_id', '=', False), ('product_tmpl_id', 'in', self.product_id.product_tmpl_id.ids),('type', '=', 'phantom')], count=True):
       raise ValidationError(_("A product with a kit-type bill of materials can not have a reordering rule."))

It is the sql_constraits taken from the warehouse, it aims to verify the product with akit type bill of materials cant have any reordering rule. If it fails, it shows an error message.

Computed Fields

In any real business scenario, we have some fields, those fields having values calculated from other fields. The calculated values from the same records or in the related records. For such a case, we can use computed fields. We can calculate the values for the fields by a function in Odoo.

A computed field is declared just like other regular fields, and it has an attribute compute. The value for the compute attribute is the name of the function as a string or a function.

Dependencies:

The value of computed fields usually depends on the value of other fields. So we can specify those dependencies on the compute method with the decorator depends(). The computation function dynamically calculates at runtime. We need to avoid inefficiently recalculating the value. So it needs to know what other fields are depending on it and need to add those fields into the decorator depends().

For example:

amount = fields.Float('Amount')
total = fields.Float('Total', compute="_compute_total")
@api.depends('amount')
def _compute_total(self):
   for rec in self:
       rec.total = 2 * rec.amount

Computed fields are not stored in the database by default. So we can use the store attribute to store the record in the database. We can use store=True attributes

For example:

total = fields.Float('Total', compute="_compute_total", store=True)

Abstract Model

In Odoo, we have three types of models, model, abstract model and transient model. We need to use a particular feature in different models like chatter, in that case, we can use an abstract model. Abstract models are based on

models.Abstract Model

class. The abstract model does not save any data, nor does it create any table.

We can define abstract models like this:

class AbstractModelName(models.Abstractmodel):
   _name = 'abstract.model'
   name = fields.Char('Name')

When we checked the database, we couldn't see any data for this model

Transient Model

In Odoo, we have three types of models, model, abstract model, and transient model. The use case of the transient model comes, for example, if we need a popup that can add some data. The popup is related to a model, and this model is used for temporary purposes. In this situation, we can use a transient model.

The Transient model is based on the model Transient model class. Moreover, the data stored in the database is temporary in this class that periodically clears data from the database table.

We can define transient models like this:

class AbstractModelName(models.Transientmodel):
   _name = 'transient.model'
   name = fields.Char('Name')

The transient model is used in creating wizards and reports.

Related Fields

In any real business scenario, we have some fields, and we need to show the value of a field from a relational model to the current model. In such a situation, we can use related fields. To do that, we need to specify the attribute related.

For example, we have a Many2one field parter_id, its comodal is res.partners, and a related field partner_name:

partner_id = fields.Many2one(‘res.partners’)

partner_name = fields.Char(‘Name’, related=”partners.name”)

By default, the related fields are not stored in the database, and also it is read-only and not copied fields. If we want to store the field record in the database, we can use store=True attributes.

partner_name = fields.Char('Name', related="partners.name", store=True)

Reference Fields

We have different types of relational models, many2one, one2many and many2many. In relational models, we can create relationships between different models. A reference field helps us to create dynamic relationships between models. In relational models, It allows only the relation between those two models by pre define related comodel. But if we are using reference field type, from a selection list the user can choose a related model and a related record can be choose from that selected model.

First we need to select the target model and then select the record In the reference field. For example, if we are having a field reference. Sometimes we need to select Purchase Order as reference, Sale Order as reference or Manufacturing Order as a reference. In this case, we can use Reference fields.

reference_field = field.Reference(selection=’’, string=’field name’)

For this, we use the selection parameter. We must assign the model and its name to this parameter.

For example:

reference = fields.Reference(selection="[('sale.order', 'Sale Order'), ('purchase.order', ' Purchase Order')]", string="Reference")

Here, we can choose a Sale Order or Purchase Order, from the same field. Also possible to selection from a function.

reference = field.Reference(selection="get_model")
@api.model
def get_model(self):
   models = self.env['ir.model'].search([])
   return [(model.model, model.name), for model in models]

Returned values must be a list.

whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message