在Odoo开发中,模型之间的关系处理至关重要。关系字段能够有效地建立起不同模型之间的联系,使数据的组织和交互更加合理、高效。今天,我们就深入探讨如何在Odoo模型中添加关系字段。
Odoo模型中的关系字段主要有三种类型:
表示多个记录关联到一个记录。例如,在宿舍管理系统中,一个房间属于一个宿舍,这种关系就是many-to-one,即多个房间关联到一个宿舍。
与many-to-one相反,一个记录可以关联多个其他记录。比如一个宿舍可以有多个房间,这就是one-to-many关系,从宿舍到房间的角度来看,一个宿舍对应多个房间。
表示多个记录可以与多个其他记录相互关联。例如,一个房间可以提供多种设施,同时一种设施也可以在多个房间中存在,这就是典型的many-to-many双向关系。
在开始添加关系字段之前,我们需要做好相应的准备。首先,我们将继续使用前一个配方中的my_hostel
附加模块。这个模块将作为我们操作的基础,为后续添加关系字段提供必要的环境和资源。
models/hostel_room.py
文件,在HostelRoom
模型类中添加m2o
字段hostel_id
,用于关联宿舍。class HostelRoom(models.Model):
_name = "hostel.room"
hostel_id = fields.Many2one("hostel.hostel", "hostel", help="Name of hostel")
这里,Many2one
的第一个参数"hostel.hostel"
指定了关联的目标模型,第二个参数"hostel"
是字段在用户界面显示的名称,help
参数提供了字段的帮助信息。
hostel_student.py
文件,并添加一些基本字段到HostelStudent
模型中,然后添加room_id
m2o
字段来连接学生和房间模型。class HostelStudent(models.Model):
_name = "hostel.student"
name = fields.Char("Student Name")
gender = fields.Selection([("male", "Male"), ("female", "Female"), ("other", "Other")], string="Gender", help="Student gender")
active = fields.Boolean("Active", default=True, help="Activate/Deactivate hostel record")
room_id = fields.Many2one("hostel.room", "Room", help="Select hostel room")
HostelRoom
模型中添加o2m
字段student_ids
,用于关联学生模型。class HostelRoom(models.Model):
_name = "hostel.room"
#...
student_ids = fields.One2many("hostel.student", "room_id", string="Students", help="Enter students")
这里,One2many
的第一个参数"hostel.student"
指定了关联的目标模型,room_id
指定了反向关联的字段。
hostel_amenities.py
文件,添加HostelAmenities
模型,包含基本字段。class HostelAmenities(models.Model):
_name = "hostel.amenities"
_description = "Hostel Amenities"
name = fields.Char("Name", help="Provided Hostel Amenity")
active = fields.Boolean("Active", help="Activate/Deactivate whether the amenity should be given or not")
HostelRoom
模型中添加m2m
字段hostel_amenities_ids
,用于关联设施模型。class HostelRoom(models.Model):
_name = "hostel.room"
#...
hostel_amenities_ids = fields.Many2many("hostel.amenities", "hostel_room_amenities_rel", "room_id", "amenitiy_id", string="Amenities", domain="[('active', '=', True)]", help="Select hostel room amenities")
这里,Many2many
的第一个参数"hostel.amenities"
指定了关联的目标模型,"hostel_room_amenities_rel"
是关系表的名称,room_id
和amenitiy_id
分别指定了在关系表中与当前模型和目标模型关联的字段,domain
参数用于筛选关联记录。
完成上述字段添加后,升级附加模块,使新字段在模型中生效。然后,将新字段添加到hostel_room.xml
文件中的视图定义中,这样新字段才能在用户界面中显示出来。
我们可以通过在开发者模式下进入Settings | Technical | Database Structure | Models
,检查模型字段来确认关系字段是否成功添加。
m2o
字段在模型表中存储另一个记录的数据库ID,这会在数据库中创建一个外键约束,确保存储的ID是对另一个表中记录的有效引用。例如,hostel_id
字段存储的是与之关联的宿舍记录的ID。index=True
属性为关系字段添加数据库索引,以提高查询性能。m2o
字段引用的记录被删除时的行为,可以通过ondelete
属性进行控制。默认选项是'set null'
,即将字段设置为空值;'restrict'
表示相关记录不能被删除;'cascade'
则表示链接的记录也将被删除。o2m
字段与m2o
字段相反,它允许从一个模型访问相关记录的列表。但它在数据库表中没有实际的列,只是一种方便在视图中显示相关记录的方式。o2m
字段,需要在另一个模型中有对应的m2o
字段。例如,student_ids
o2m
字段通过room_id
字段与HostelRoom
模型建立关联。m2m
字段在模型表中没有列,而是使用数据库中的另一个表来存储两个模型之间的关系。这个关系表有两列,分别用于存储相关记录的ID。当使用m2m
字段关联房间和设施时,会在关系表中创建一条新记录,包含房间的ID和设施的ID。m2m
字段创建关系表,默认名称由两个模型的名称按字母顺序排序后加上_rel
后缀组成。如果两个模型名称过长,可以使用relation
属性更改关系表名称。同时,要注意关系表的主键索引名称也有长度限制,如果默认名称超过限制,需要手动设置更短的名称。hostel_amenities_ids
字段中,可以使用domain="[('active', '=', True)]"
来只显示激活状态的设施。m2o
字段的auto_join
属性时,虽然它可以让ORM使用SQL连接提高性能,但可能会跳过用户访问控制和记录访问规则检查,所以应谨慎使用,尽量避免使用该属性。m2m
字段时,必须为每个字段分配不同的关系表名称,以避免冲突。关于关系字段的context
和domain
属性的更多详细信息,可以参考第9章“Backend Views”。