- 上传者: Administrator
- 上传时间:2023年11月14日 01时16分10秒
* Constraints ** *** Any real-world business scenario has a chance that users provide inaccurate data. Constraints allow us to stop users from submit ......
Constraints
Any real-world business scenario has a chance that users provide inaccurate data. Constraints allow us to stop users from submitting inaccurate data. In order to prevent inaccurate data from being recorded before the record is saved, constraints are limits set on the record.
Two approaches
The two tools given by Odoo for automatically validating invariants are Python Constraints and SQL Constraints.
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."),]
This is the sql_constraints taken from the sale order. It aims to verify the confirmed sale order has a confirmation date. If the sql_constraints fails, then it will show an error message. The SQL constraint will always be specified in the field declaration section of the Python code; it is defined before entering the coding section.
Python Constraints:
Data consistency can be efficiently ensured using SQL constraints. To ensure data consistency in other situations, we might need to utilize more complicated tests. In such situations, we can use python constraints.
The Python constraint is a method decorated with constraints(). It is included on a record of the set. Decorators are used to specifying which fields are involved in the constraints. When a field is changed, these constraints are automatically considered.
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_constraints that were taken from the warehouse, and it checks to make sure that any reordering rules cannot apply to a product with a kit-type bill of materials. If it doesn't work, an error message appears.
Computed Fields
In any real-world business scenario, there are some fields with values derived from other fields. The calculated values are either from the same records or from records that are connected to them. We can take advantage of computed fields in this situation. We can use an Odoo function to calculate the values for the fields.
Computed fields in Odoo have the same definition as other ordinary fields in Odoo. The attribute calculate, which is used to give the name of the function used for its computation, is the only exception. At runtime, computed fields are dynamically calculated. Unless you add such support directly by yourself, they are not searchable or writable.
A computed field has the same attribute ‘compute’ as other normal fields when it is declared. The name of the function as a string or as a function is the value for the compute attribute.
Dependencies:
Usually, the values of other fields affect the values of computed fields. Therefore, using the decorator depends(), we can define those requirements on the compute method. At runtime, the computation function performs dynamic calculations. We must avoid from recalculating the value inefficiently.
Hence, it needs to be aware of the other fields that depend on it and must include those fields in 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.0 * rec.amount
Here, we can calculate the total by using the function _compute_total. By default, computed fields are not kept in the database. In order to store the record in the database, we can use the store property.
We can use the store = True flag
For example,
total = fields.Float('Total', compute="_compute_total", store=True)
So, rather than having to be recomputed at runtime, they may be obtained just like any other regular fields. The ORM will be able to determine when these stored values need to be updated and recalculated.
Inverse Function
We know that by default, the computed fields are read-only. Which means the user couldn’t set the value for the computed fields. In some cases, it might be useful to still be able to set a value directly. For that, Odoo provides the ability to use an inverse function:
total = fields.Float(compute="_compute_total", inverse="_inverse_total")
amount = fields.Float()
@api.depends("amount")
def _compute_total(self):
for record in self:
record.total = 2.0 * record.amount
def _inverse_total(self):
for record in self:
record.amount = record.total / 2.0
The field is set by a compute method, and the field's dependencies are generated by an inverse method. When saving a record, the inverse method is called, and the compute method is activated whenever one of its dependencies changes.
Related Fields
We need to demonstrate the benefit of a field from a relational model to the current model in any real-world business scenario where we have some fields. 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 partner_id, and its comodel is res.partners, and a related field is partner_name:
partner_id = fields.Many2one('res.partners')
partner_name = fields.Char('Name', related="partner_id.name")
Related fields are read-only and not copied by default, nor are they stored in the database. Using the store = True attributes, we can store the field record in the database.
partner_name = fields.Char('Name', related="partner_id.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. Relational models only permit the relationship between the two models by defining a related comodel in advance. However, if we utilize the reference field type, the user can select a related model from a list of options and a related record from that model.
We must first choose the target model before choosing the record in the reference field. For instance, let's say we need a field reference. We may sometimes need to choose a manufacturing order, sale order, or purchase order as a reference. We can use Reference fields in this situation.
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.
- 微信扫一扫,一分也是爱:
服务原则及地区范围
宜兴通达网络科技有限公司,地处中国宜兴环科园内,是一家高新技术企业。公司在企业网络维护和企业信息化建设与咨询方面,有10多年经验。
我公司愿与客户一道,力求彻底解决客户问题!
我们不是在给企业提供“头痛医头、脚痛医脚”的暂时解决方案,而是在部署根本性安全与稳定服务!!
我们愿携手客户,建立企业IT规划;杜绝随意安装系统、软件等操作;力求共同维护有序、安全、稳定的网络办公环境!!!
IT服务,服务是根本,客户是上帝;我们提供快速响应、快速上门、快速排查,提供优质高效的服务!!!!
通达科技提供全国范围内的服务,服务形式包括远程协助、电话咨询、电子邮件咨询、传真咨询、问答平台的问题解决等。
宜兴地区提供上门服务:
- 市区服务:宜城街道、城北街道(屺亭街道)、新街街道、新庄街道、环科园、渚桥开发区
- 市郊服务:张渚镇、西渚镇、太华镇、徐舍镇、官林镇、杨巷镇、新建镇、和桥镇、高塍镇、万石镇、周铁镇、芳桥镇、丁蜀镇、湖父镇。