Odoo提供了两种方法来自动验证不变性:Python约束SQL约束

Python约束使用constrains()修饰方法,并在记录集上调用。该修饰指定约束中包含哪些字段,以便在修改其中一个字段时自动评估约束。如果不满足其不变性,则该方法将引发异常:

from odoo.exceptions import ValidationError

@api.constrains('age')
def _check_something(self):
    for record in self:
        if record.age > 20:
            raise ValidationError("Your record is too old: %s" % record.age)
    # all records passed the test, don't return anything

行使
添加Python约束

添加一个约束,以检查教师在其自己的会话的出席者中是否不存在。

openacademy / models.py

# -*- coding: utf-8 -*-

from odoo import models, fields, api, exceptions

class Course(models.Model):
    _name = 'openacademy.course'
                    'message': "Increase seats or remove excess attendees",
                },
            }

    @api.constrains('instructor_id', 'attendee_ids')
    def _check_instructor_not_in_attendees(self):
        for r in self:
            if r.instructor_id and r.instructor_id in r.attendee_ids:
                raise exceptions.ValidationError("A session's instructor can't be an attendee")

SQL约束是通过model属性定义的 _sql_constraints。分配给弦的三元组的列表,后者是(name, sql_definition, message),这里name是一个有效的SQL约束名,sql_definition是一种table_constraint表达,并且message是错误消息。

行使
添加SQL约束

在PostgreSQL的文档的帮助下,添加以下约束:

检查课程说明和课程名称是否不同
使课程名称唯一
openacademy / models.py

    session_ids = fields.One2many(
        'openacademy.session', 'course_id', string="Sessions")

    _sql_constraints = [
        ('name_description_check',
         'CHECK(name != description)',
         "The title of the course should not be the description"),

        ('name_unique',
         'UNIQUE(name)',
         "The course title must be unique"),
    ]


class Session(models.Model):
    _name = 'openacademy.session'

行使
练习6-添加重复选项

由于我们为课程名称的唯一性添加了一个约束,因此无法再使用“复制”功能(表格‣复制)。

重新实现自己的“复制”方法,该方法可以复制“课程”对象,将原始名称更改为“ [原始名称]的副本”。

openacademy / models.py

    session_ids = fields.One2many(
        'openacademy.session', 'course_id', string="Sessions")

    def copy(self, default=None):
        default = dict(default or {})

        copied_count = self.search_count(
            [('name', '=like', u"Copy of {}%".format(self.name))])
        if not copied_count:
            new_name = u"Copy of {}".format(self.name)
        else:
            new_name = u"Copy of {} ({})".format(self.name, copied_count)

        default['name'] = new_name
        return super(Course, self).copy(default)

    _sql_constraints = [
        ('name_description_check',
         'CHECK(name != description)',