模型之间的关系
来自模型的记录可能与来自另一模型的记录相关。例如,一个销售订单记录和一个包含客户数据的客户记录相关;同时也和销售订单线记录相关。
练习
创建会话模型
对于模块Open Academy,我们考虑一个会话模型:会话是在给定时间为给定听众授课的课程。
为会话创建模型。一个会话有一个名字,一个开始日期,一个持续时间和一些座位。 添加一个动作和菜单项来显示它们。通过菜单项使新模型可见。
- 在openacademy/models/models.py中创建类Session
- 在openacademy/view/openacademy.xml中添加对会话对象的访问
openacademy/models.py
name = fields.Char(string="Title", required=True)
description = fields.Text()
class Session(models.Model):
_name = 'openacademy.session'
name = fields.Char(required=True)
start_date = fields.Date()
duration = fields.Float(digits=(6, 2), help="Duration in days")
seats = fields.Integer(string="Number of seats")
openacademy/views/openacademy.xml
session.form
openacademy.session
Sessions
openacademy.session
form
tree,form
注
digits=(6, 2)
指定浮点数的精度:6是数字的总数,而2是逗号后的位数。注意逗号之前的数字的位数最大为4
关系字段链接记录,即相同模型(层次结构)或不同模型之间的记录。
关系字段类型为:
Many2one(other_model, ondelete='set null')
与其他对象的简单链接:
print foo.other_id.name
请参阅
foreign keys
One2many(other_model, related_field)
一个虚拟关系,一个Many2one
的逆关系。One2many
表现为一个记录容器,访问它导致一组(可能是空的)记录集合:
for other in foo.other_ids:
print other.name
危险
因为One2many
是一个虚拟关系,所以必须在other_model中有一个Many2one
字段,它的名字必须是related_field
Many2many(other_model)
双向多重关系,任何一方的记录都可以与另一方的任何数量的记录相关。作为记录容器,访问它也会导致一个可能的空记录集:
for other in foo.other_ids:
print other.name
练习
多对一关系
使用many2one,修改Course 和Session模型,以反映它们与其他模型的关系:
- course有一个responsible用户;那个字段的值是内置模型res.users的记录
- session有一个instructor;该字段的值是一个内置的模型res.partner记录
- session和course是相关的;其字段的值是模型openacademy.course的记录,也是必须的
- 适配视图
- 将相关的Many2one字段添加到模型中,以及
- 在视图中添加它们
openacademy/models.py
name = fields.Char(string="Title", required=True)
description = fields.Text()
responsible_id = fields.Many2one('res.users',
ondelete='set null', string="Responsible", index=True)
class Session(models.Model):
_name = 'openacademy.session'
start_date = fields.Date()
duration = fields.Float(digits=(6, 2), help="Duration in days")
seats = fields.Integer(string="Number of seats")
instructor_id = fields.Many2one('res.partner', string="Instructor")
course_id = fields.Many2one('openacademy.course',
ondelete='cascade', string="Course", required=True)
openacademy/views/openacademy.xml
course.tree
openacademy.course
session.tree
openacademy.session
Sessions
openacademy.session
练习
逆一对多关系
使用逆关系字段one2many,修改模型以反映courses 与sessions之间的关系
- 修改
Course
类,并且 - 在course 表单视图中添加字段
openacademy/models.py
responsible_id = fields.Many2one('res.users',
ondelete='set null', string="Responsible", index=True)
session_ids = fields.One2many(
'openacademy.session', 'course_id', string="Sessions")
class Session(models.Model):
openacademy/views/openacademy.xml
练习
多重多对多关系
使用关系字段many2many,修改Session模型以将每个session 与一组attendees联系起来。Attendees 将由partner 记录表示,因此我们将关联内置的模型res.partner。相应地调整视图。
- 修改
Session
类,并且 - 在表单视图中添加字段
openacademy/models.py
instructor_id = fields.Many2one('res.partner', string="Instructor")
course_id = fields.Many2one('openacademy.course',
ondelete='cascade', string="Course", required=True)
attendee_ids = fields.Many2many('res.partner', string="Attendees")
openacademy/views/openacademy.xml
继承
模型继承
Odoo提供了两种继承机制,以模块化方式扩展现有模型。
第一个继承机制允许一个模块修改另一个模块中定义一个模型的行为:
- 将字段添加到模型中
- 重写模型上字段的定义
- 向模型添加约束
- 将方法添加到模型中
- 重写模型上的现有方法
第二继承机制(委托)允许将模型的每个记录链接到父模型中的记录,并提供对父记录的字段的透明访问。
请参阅
_inherit
_inherits
代替修改现有的视图(通过重写它们),Odoo提供的视图继承让子视图“扩展”的视图应用在顶部的根视图,并可以从父视图中添加或删除内容。
扩展视图使用inherit_id
字段引用它的父类,而不是单个视图,其arch
字段由任意数量的xpath
元素组成,它们选择和改变父视图的内容:
id.category.list2
idea.category
expr
在父视图中XPath表达式选择单个元素。如果不匹配元素或多于一个,则会引发错误
position
应用于匹配元素的操作:
inside
在匹配元素的末尾追加xpath的body
replace
替换使用xpath的body的匹配元素,替换任何 $0
节点发生在使用原始元素的新的body中
before
在匹配元素之前插入xpat的body作为兄弟
after
匹配元素之后插入xpat的body作为兄弟
attributes
使用在xpath的body中的特殊的attribute
元素改变匹配元素的属性
提示
当匹配一个元素,position
属性可以直接设置在元素上以便被发现。下面的两个继承将给出相同的结果
练习
更改现有内容
- 使用模型继承,修改现有的Partner 模型以添加
instructor
布尔字段,以及对应于session-partner关系的many2many 字段 - 使用视图继承,在partner表单视图中显示此字段
注
这是引入开发者模式来检查视图、找到其外部ID和放置新字段的位置的机会
- 创建文件
openacademy/models/partner.py
并在__init__.py
中导入 - 创建文件
openacademy/views/partner.xml
并在__manifest__.py中添加
openacademy/__init__.py
# -*- coding: utf-8 -*-
from . import controllers
from . import models
from . import partner
openacademy/__manifest__.py
# 'security/ir.model.access.csv',
'templates.xml',
'views/openacademy.xml',
'views/partner.xml',
],
# only loaded in demonstration mode
'demo': [
openacademy/partner.py
# -*- coding: utf-8 -*-
from odoo import fields, models
class Partner(models.Model):
_inherit = 'res.partner'
# Add a new column to the res.partner model, by default partners are not
# instructors
instructor = fields.Boolean("Instructor", default=False)
session_ids = fields.Many2many('openacademy.session',
string="Attended Sessions", readonly=True)
openacademy/views/partner.xml
partner.instructor
res.partner
Contacts
res.partner
tree,form
域
在Odoo中,域是对记录条件进行编码的值。一个域是一个列表,用于选择一个模型的记录子集的标准。每个标准是一个三元组,有一个字段名、一个运算符和一个值。
例如,当使用Product 模型下列域选择所有是服务且单价超过1000的产品:
[('product_type', '=', 'service'), ('unit_price', '>', 1000)]
默认情况下,标准使用隐式的AND联合。逻辑运算符 &
(AND), |
(OR) 和!
(NOT)可用来显示的联合标准。它们在前缀位置中使用(操作符在其参数之前插入而不是在它们之间)。例如,选择合适的产品“其是服务或有单价不是在1000和2000之间”:
['|',
('product_type', '=', 'service'),
'!', '&',
('unit_price', '>=', 1000),
('unit_price', '
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【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脚手架写一个简单的页面?