多对多关系

来自Odoo大V社-odoo中文开发手册
7017511讨论 | 贡献2017年5月4日 (四) 05:55的版本

跳转至: 导航搜索

Many2many 最少要提供一个参数,也就是关联的模块,建议使用string参数,以便更好的标题展示。

在数据库层面,数据库表中是不会添加任何字段。它会自动的创建一个新的中间表,这个表只有两个外键ID字段,并且这两个字段分别关联对应的数据库表。这个中间表和字段的名字都是自动生成的。中间表的名字是两个表的名字用下划线拼接后在加上_rel组成的。

有时候,我们可能需要改变这种自动的默认值。

其中的一种情况就是,关联的模块有很长的名字,那么自动生成的中间表的名称就会很长,可能会超出PostgreSQL对于表名不得多于63个字符的限制。这种情况下,我们就需要手动选择一个不超出限制的名字。

另一种情况,在相同的模块中需要两个many2many的关系。这种情况,我们也需要手动的为中间表添加名称,只有这样,才能避免数据库名称冲突。

有两种方式去手动的设置这些值:按位置传值或指定参数名传值

使用按位置传值的方式,字段的定义如下:

# Task <-> Tag relation (positional args):
tag_ids = fields.Many2many(
    'todo.task.tag',       # related model
    'todo_task_tag_rel',   # relation table name
    'task_id',             # field for "this" record
    'tag_id',              # field for "other" record
    string='Tags')
  • 注意
这些位置参数都是可选的。我们可以只设置中间表的名称,而让它的字段名称自动生成。

我们也可以使用指定参数名称的方式赋值,那样更具有可读性:

# Task <-> Tag relation (keyword args):
    tag_ids = fields.Many2many(
    comodel_name='todo.task.tag',   # related model
    relation='todo_task_tag_rel',   # relation table name
    column1='task_id',              # field for "this" record
    column2='tag_id',               # field for "other" record
    string='Tags') 

和many2one字段相似,many2many字段也可以定义domain和context等关键属性

  • 注意
目前,由于ORM的局限性,对于抽象模块(Abstract models),当强制命名中间表的名称和列名称后,它们就不能被继承修改了。所以对于抽象模块,请谨慎使用。

Many2many相反的关系也是Many2many。如果我们为Tags模块添加了一个Many2many的字段,ODOO会判定,在Task模块中就会存在一个相反的many2many关系。

在Tags模块中,与Tasks相反的关系可以如下定义:

class Tag(models.Model):
    _name = 'todo.task.tag'
    # Tag class relationship to Tasks:
    task_ids = fields.Many2many(
        'todo.task', # related model
        string='Tasks')
上一节:多对一关系 下一节:一对多反向关系