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.