odoo17 | 视图字段验证约束

前言

前一章介绍了向模型添加一些业务逻辑的能力。现在我们可以将按钮链接到业务代码,但是我们如何防止用户输入错误的数据呢?例如,在我们的房地产模块中,没有什么可以阻止用户设置负预期价格。

Odoo提供了两种方法来设置自动验证的不变量:Python约束和SQL约束。

SQL约束

目标

  • 金额应严格限制为正数
  • 属性类型和标记应具有唯一的名称

    SQL约束是通过模型属性**_sql_constraints定义的。这个属性被分配一个包含字符串(name、sql_definition、message)的三元组列表,其中 name是一个有效的SQL约束名称,sql_definition是一个 table_constraint**表达式,message 是错误消息。
    您可以在这里找到一个简单的示例:
python 复制代码
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from collections import defaultdict
from odoo import api, fields, models, _
from odoo.osv import expression
from odoo.exceptions import ValidationError


class AccountAnalyticDistribution(models.Model):
    _name = 'account.analytic.distribution'
    _description = 'Analytic Account Distribution'
    _rec_name = 'account_id'

    account_id = fields.Many2one('account.analytic.account', string='Analytic Account', required=True)
    percentage = fields.Float(string='Percentage', required=True, default=100.0)
    name = fields.Char(string='Name', related='account_id.name', readonly=False)
    tag_id = fields.Many2one('account.analytic.tag', string="Parent tag", required=True)

    _sql_constraints = [
        ('check_percentage', 'CHECK(percentage >= 0 AND percentage <= 100)',
         'The percentage of an analytic distribution should be between 0 and 100.')
    ]
  • name 为 check_percentage
  • sql_definition 为 CHECK(percentage >= 0 AND percentage <= 100)
  • message 为 The percentage of an analytic distribution should be between 0 and 100.

如果某些产品/服务的价格为零,则无法应用约束。您可以删除 有问题的数据,以便应用新的约束。

Python约束

*odoo.api.constrains(args)

修饰约束检查器。

每个参数必须是检查中使用的字段名:

python 复制代码
@api.constrains('name', 'description')
def _check_description(self):
    for record in self:
        if record.name == record.description:
            raise ValidationError("Fields name and description must be different")

在其中一个命名字段已被修改的记录上调用。

如果验证失败,将引发ValidationError。

警告

@constraints 只支持简单的字段名,不支持带点的名称(关系字段的字段,例如partner_id.customer),并且会被忽略。

只有当修饰方法中声明的字段包含在createwrite 调用中时,@constraints 才会被触发。这意味着视图中不存在的字段将不会在创建记录期间触发调用。create的重写是必要的,以确保约束总是会被触发(例如,测试是值是否为空)。

  • 也可以传递单个函数作为参数。在这种情况下,字段名是通过调用带有模型实例的函数来给出的。

目标

  • 设置报价不能低于预期价格的 90%。

    SQL约束是确保数据一致性的有效方法。然而,可能需要进行更复杂的检查,这需要Python代码。在这种情况下,我们需要一个Python约束。

Python约束被定义为一个用constraints()修饰的方法,并在记录集上调用。装饰符指定约束中涉及哪些字段。当修改这些字段中的任何一个时,将自动评估约束。如果不满足其不变量,该方法预计会引发异常:

python 复制代码
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

在这里可以找到一个简单的例子:

python 复制代码
    @api.constrains('product_id')
    def check_product_id(self):
        if any(elem.product_id.type != 'product' for elem in self):
            raise ValidationError(_('Quants cannot be created for consumables or services.'))

    @api.constrains('quantity')
    def check_quantity(self):
        for quant in self:
            if quant.location_id.usage != 'inventory' and quant.lot_id and quant.product_id.tracking == 'serial' \
                    and float_compare(abs(quant.quantity), 1, precision_rounding=quant.product_uom_id.rounding) > 0:
                raise ValidationError(_('The serial number has already been assigned: \n Product: %s, Serial Number: %s') % (quant.product_id.display_name, quant.lot_id.name))

    @api.constrains('location_id')
    def check_location_id(self):
        for quant in self:
            if quant.location_id.usage == 'view':
                raise ValidationError(_('You cannot take products from or deliver products to a location of type "view" (%s).') % quant.location_id.name)
  • SQL 约束通常比 Python 约束更有效。当性能至关重要时,始终 首选 SQL 而不是 Python 约束。

我们的房地产模块开始看起来不错。我们添加了一些业务逻辑,现在我们确保 数据是一致的。但是,用户界面仍然有点粗糙。让我们看看如何 在下一章中改进它。

相关推荐
程序员的世界你不懂1 分钟前
Appium+python自动化(二十一)- Monkey指令操作手机
python·appium·自动化
belldeep24 分钟前
python 在基因研究中的应用,博德研究所:基因编辑
python·基因·broad institute·博德研究所·基因编辑
XMYX-01 小时前
Python 实现一个带进度条的 URL 批量下载工具(含 GUI 界面)
开发语言·python
未来并未来2 小时前
Sentinel 流量控制安装与使用
开发语言·python·sentinel
东皇太星2 小时前
Python 100个常用函数全面解析
开发语言·python
luofeiju3 小时前
数字图像处理与OpenCV初探
c++·图像处理·python·opencv·计算机视觉
壹米饭4 小时前
Java程序员学Python学习笔记一:学习python的动机与思考
java·后端·python
电院工程师4 小时前
SM3算法Python实现(无第三方库)
开发语言·python·算法·安全·密码学
CodeDevMaster4 小时前
在Jupyter Notebook中使用Conda虚拟环境
python·jupyter
冷月半明5 小时前
告别手动拖动!Python+dddocr自动化破解多缺口滑块
python