模型约束
Odoo提供了两种设置自动验证不变量的方法: Python constraints
和SQL constraints
.
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约束
添加一个约束,该约束检查instructor在他/她自己的session的attendees中不存在。
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约束是通过模型属性_sql_constraints
定义的。后者被分配给字符串的三元组列表(name, sql_definition, message),其中name
是有效的SQL约束名称,sql_definition
是table_constraint表达式,message
是错误消息。
练习
添加SQL约束
在PostgreSQL's documentation的帮助下,添加以下约束:
- CHECK (检查)课程描述和课程名称是不同的
- 使Course的name UNIQUE(唯一的)
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 - 添加重复选项
因为我们为课程名称的唯一性添加了一个约束,所以不再可能使用“复制”函数 (Form ‣ Duplicate)。
重新实现你自己的“复制”方法,允许复制课程对象,把原来的名字改成“[原始名字]的拷贝”。
openacademy/models.py
session_ids = fields.One2many(
'openacademy.session', 'course_id', string="Sessions")
@api.multi
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)',
高级视图
树视图
树视图可以采取补充属性来进一步定制他们的行为:
decoration-{$name}
允许根据相应的记录属性更改行文本的样式。
值是Python表达式。对于每个记录,表达式以记录的属性作为上下文值来评估,如果为true,则将相应的样式应用于行。 其他上下文值是uid
(当前用户的id) 和current_date
(当前日期为yyyy-MM-dd形式的字符串)。
{$name}
可以是 bf
(font-weight: bold
), it
(font-style: italic
),或任何的bootstrap contextual color (danger
,info
, muted
, primary
, success
or warning
).
editable
要么是 "top"
要么是 "bottom"
。使树视图可就地编辑(而不是必须通过表单视图),该值是新行出现的位置
练习
列表颜色
修改Session树视图的方式是持续少于5天的会话是蓝色的,而持续超过15天的则是红色的。
修改Session树视图:
openacademy/views/openacademy.xml
session.tree
openacademy.session
日历视图
将记录显示为日历事件。它们的根元素是,它们最常见的属性是:
color
用于颜色分割的字段的名称。颜色被自动分配给事件,但是相同颜色段中的事件(具有与它们的@color字段相同的值的记录)将被赋予相同的颜色
date_start
记录的字段保存事件的开始日期/时间
date_stop
(可选的)
记录字段保存事件的结束日期/时间
字段(定义每个日历事件的标签 )
练习
日历视图
向Session模型添加日历视图,使用户能够查看与Open Academy相关的事件。
-
添加从start_date和duration计算的AA字段end_date
提示
逆函数使字段可写,并允许在日历视图中移动会话(通过拖放)
- 向Session 模型添加日历视图
- 并将日历视图添加到Session 模型的动作中
openacademy/models.py
# -*- coding: utf-8 -*-
from datetime import timedelta
from odoo import models, fields, api, exceptions
class Course(models.Model):
attendee_ids = fields.Many2many('res.partner', string="Attendees")
taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')
end_date = fields.Date(string="End Date", store=True,
compute='_get_end_date', inverse='_set_end_date')
@api.depends('seats', 'attendee_ids')
def _taken_seats(self):
},
}
@api.depends('start_date', 'duration')
def _get_end_date(self):
for r in self:
if not (r.start_date and r.duration):
r.end_date = r.start_date
continue
# Add duration to start_date, but: Monday + 5 days = Saturday, so
# subtract one second to get on Friday instead
start = fields.Datetime.from_string(r.start_date)
duration = timedelta(days=r.duration, seconds=-1)
r.end_date = start + duration
def _set_end_date(self):
for r in self:
if not (r.start_date and r.end_date):
continue
# Compute the difference between dates, but: Friday - Monday = 4 days,
# so add one day to get 5 days instead
start_date = fields.Datetime.from_string(r.start_date)
end_date = fields.Datetime.from_string(r.end_date)
r.duration = (end_date - start_date).days + 1
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
for r in self:
openacademy/views/openacademy.xml
session.calendar
openacademy.session
Sessions
openacademy.session
form
tree,form,calendar
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?