Chapter 10: Constraints
第十章:约束
原文来自:
https://www.odoo.com/documentation/17.0/zh_CN/developer/tutorials/server_framework_101/10_constraints.html
使用通义千问翻译。
测试代码:https://gitee.com/zhang-wei918/estate
The previous chapter introduced the ability to add some business logic to our model. We can now link buttons to business code, but how can we prevent users from entering incorrect data? For example, in our real estate module nothing prevents users from setting a negative expected price.
上一章介绍了向我们的模型添加业务逻辑的能力。现在我们可以将按钮与业务代码链接起来,但是如何防止用户输入错误的数据呢?例如,在我们的房地产模块中,没有任何机制阻止用户设置负数的预期价格。
Odoo provides two ways to set up automatically verified invariants: Python constraints
and SQL constraints
.
Odoo提供了两种自动验证不变量的方法:Python约束和SQL约束。
SQL
Reference: the documentation related to this topic can be found in Models and in the PostgreSQL’s documentation.
参考:关于此主题的文档可以在“模型”中找到,同时也可以查阅PostgreSQL的官方文档。
注解
Goal: at the end of this section: 目标:在本节结束时:
- Amounts should be (strictly) positive 对金额的约束
- Property types and tags should have a unique name
房产类型和标签应具有唯一名称
SQL constraints are defined through the model attribute _sql_constraints
. This attribute is assigned a list of triples containing strings (name, sql_definition, message)
, where name
is a valid SQL constraint name, sql_definition
is a table_constraint expression and message
is the error message.
SQL约束是通过模型属性 _sql_constraints
定义的。这个属性被分配了一个三元组列表,包含字符串(名称,SQL定义,消息),其中名称是一个有效的SQL约束名称,SQL定义是一个表约束表达式,消息是错误信息。
You can find a simple example here. 你可以在这里找到一个简单的示例。
Exercise
Add SQL constraints. 添加SQL约束。
Add the following constraints to their corresponding models:
为相应的模型添加以下约束:
- A property expected price must be strictly positive
房产的预期价格必须严格为正数 - A property selling price must be positive
房产的销售价格必须为正数 - An offer price must be strictly positive
报价的价格必须严格为正数 - A property tag name and property type name must be unique
房产标签名称和房产类型名称必须唯一
Tip: search for the unique
keyword in the Odoo codebase for examples of unique names.
提示:在Odoo代码库中搜索“unique”关键字,以获取唯一名称的示例。
Restart the server with the -u estate
option to see the result. Note that you might have data that prevents a SQL constraint from being set. An error message similar to the following might pop up:
使用 -u estate
选项重启服务器以查看结果。请注意,可能存在阻止设置SQL约束的数据。可能出现类似以下的错误消息:
ERROR rd-demo odoo.schema: Table 'estate_property_offer': unable to add constraint 'estate_property_offer_check_price' as CHECK(price > 0)
For example, if some offers have a price of zero, then the constraint can’t be applied. You can delete the problematic data in order to apply the new constraints.
例如,如果某些报价的价格为零,则无法应用约束。你可以删除问题数据,以便应用新的约束。
Python
Reference: the documentation related to this topic can be found in constrains()
.
参考:关于此主题的文档可以在 constrains()
中找到。
注解
Goal: at the end of this section, it will not be possible to accept an offer lower than 90% of the expected price.
目标:在本节结束时,将不可能接受低于预期价格90%的报价。
SQL constraints are an efficient way of ensuring data consistency. However it may be necessary to make more complex checks which require Python code. In this case we need a Python constraint.
SQL约束是确保数据一致性的有效方式。然而,有时可能需要更复杂的检查,这需要Python代码。在这种情况下,我们需要一个Python约束。
A Python constraint is defined as a method decorated with constrains()
and is invoked on a recordset. The decorator specifies which fields are involved in the constraint. The constraint is automatically evaluated when any of these fields are modified . The method is expected to raise an exception if its invariant is not satisfied:
Python约束被定义为使用 constrains()
装饰器修饰的方法,并在记录集上调用。装饰器指定了哪些字段参与约束。当这些字段中的任何一个被修改时,约束会自动评估。如果约束的不变量不满足,该方法应该抛出异常:
from odoo.exceptions import ValidationError ... @api.constrains('date_end') def _check_date_end(self): for record in self: if record.date_end < fields.Date.today(): raise ValidationError("The end date cannot be set in the past") # all records passed the test, don't return anything
A simple example can be found here. 一个简单的示例可以在这里找到。
Exercise
Add Python constraints. 添加Python约束。
Add a constraint so that the selling price cannot be lower than 90% of the expected price.
添加一个约束,使得销售价格不能低于预期价格的90%。
Tip: the selling price is zero until an offer is validated. You will need to fine tune your check to take this into account.
提示:销售价格在报价被确认前为零。你需要仔细调整检查以考虑这一点。
警告
Always use the float_compare()
and float_is_zero()
methods from odoo.tools.float_utils
when working with floats!
处理浮点数时,始终使用 odoo.tools.float_utils
中的 float_compare()
和 float_is_zero()
方法!
Ensure the constraint is triggered every time the selling price or the expected price is changed!
确保在销售价格或预期价格更改时触发约束!
SQL constraints are usually more efficient than Python constraints. When performance matters, always prefer SQL over Python constraints.
通常,SQL约束比Python约束更高效。当性能至关重要时,总是优先选择SQL约束而不是Python约束。
Our real estate module is starting to look good. We added some business logic, and now we make sure the data is consistent. However, the user interface is still a bit rough. Let’s see how we can improve it in the next chapter.
通常,SQL约束比Python约束更高效。当性能至关重要时,总是优先选择SQL约束而不是Python约束。
发表回复