odoo14 入门解刨关联字段
Odoo中关联字段是用来绑定表与表之间主从关系的。
主从关系指:
首先必须要明白id的存在的意义,它具备“唯一”的属性,也就是表中所有记录中该字段的值不会重复。
假设表A存储是身份证信息,表B存储的是银行卡信息,表B中有一个字段是表A的id,那么我们是不是可以通过身份证id去查询这个人有多少张银行卡?
id的概念是贯穿整个odoo的,因为具有唯一属性的值可以作为数据表的聚集索引,如果理解聚集索引应该就明白,在数亿记录中查询数据和数万记录中查询数据的速度几乎没有区别的。
Odoo中的关联字段都是围绕这个id来进行操作的。
Odoo中的关联字段有:
1.Many2one 主表中创建一个字段来存储从表记录的id。这就意味着主表的每条记录只能关联从表中的一条记录。打个比方,银行卡记录表是主表,我们的身份证是从表,每张银行卡只能属于一个人,也就是每张银行卡只能关联一个身份证。
2.One2many 和上边的Many2one是相反的,主表是身份证,从表是银行卡,一个身份证可以拥有多张银行卡。One2many和Many2one一起使用的时候主从表数据可以互通。odoo中创建这个字段的时候,odoo会创建一张视图来处理他们的关系,获取从表中的id和从表中的存储Many2one字段组成的视图。
3.Many2many 和One2many不一样,odoo会生成辅助表来存储主从表id与id之间的关联,辅助表中有两个字段,一个是主表的id,一个是从表的id,所以这里每个主表id可以与多个从表id关联。和Many2one不同的是,Many2many是单项关联从表,所以从表并不知道。如:身份证表中关联了多张银行卡,但银行卡中没有身份证id的字段;这样的话通过身份证可以得到银行卡的信息,但却不能通过银行卡得到身份证的信息。
1 class BookCategory(models.Model): 2 _name = 'library.book.category' 3 4 _parent_store = True 5 _parent_name = "parent_id" # optional if field is 'parent_id' 6 7 name = fields.Char('Category') 8 # Many2one 9 parent_id = fields.Many2one( 10 'library.book.category', 11 string='Parent Category', 12 ondelete='restrict', 13 index=True 14 ) 15 # One2many 16 child_ids = fields.One2many( 17 'library.book.category', 'parent_id', 18 string='Child Categories') 19 20 21 22 # Many2many 23 def _default_author_ids(self): 24 return return [(6,0,[self.env.user.id])] 25 def _domain_author_ids(self): 26 return [('company_id','=',self.env.user.company_id.id)] 27 # res.partner:关联那个model 28 # v_Many2many_author:Many2many字段是通过视图实现的,这里指定视图名。也可以不指定,不指定的话接下来的两个参数也不需要设置了 29 # book_id:本表id 30 # partner_id: 关联表id 31 # default: 你还可以设置默认值(所有字段都可以设置) 32 # readonly: 只读,在form中不可编辑(所有字段都可以设置) 33 # copy: 表单中action复制功能不携带该字段一起复制(所有字段都可以设置)。 34 # states:如果你在表中存在state字段,这里就是根据state字段值来更变它的只读属性。或者invisible是否显示。(所有字段都可以设置) 35 # domain: 过滤。关联字段都能用 36 author_ids = fields.Many2many('res.partner', 37 'v_Many2many_author', 'book_id', 'partner_id', 38 string='Authors', 39 default=_default_author_ids, 40 readonly=True, 41 copy=False, 42 states={'20': [('readonly', False)], '105': [('readonly', False)]}, 43 domain=_domain_author_ids) 44 45 parent_path = fields.Char(index=True) 46 47 @api.constrains('parent_id') 48 def _check_hierarchy(self): 49 if not self.parent_id._check_recursion():#因为主从都是自己表记录,所以这里要防止出现递归 50 raise models.ValidationError('Error! You cannot create recursive categories.')
1 #Many2many你可以指定生成辅助表的名字 2 #第一个参数是模型名,第二个参数是指定表名,第三个参数是存储主表id的列名,第四个参数是存储从表id的列名。这里domain参数作用是,当你关联数据的时候会自动过滤数据用(该参数在所有关联字段中都可以用)。 3 right_ids = fields.Many2many('res.groups', 'ship_manage_group_right_rel', 'gid', 'rid', string="Rights", domain=[('name','like','Book')])
1 #create的时候关联字段如何填写值 2 #Many2one的值直接填写关联表的id就行 3 #One2many和Many2many的值为list,每个对象都是元组: 4 #(0,0,dict_val) 创建一个新的关联记录 5 #(6,0,id_list) 关联已有的记录的id 6 slef.env['library.book'].create({ 7 'name':'Linux C', 8 'author_ids':[(0,0,{'name':'张三'}),(0,0,{'name':'李四'}),(6,0,[1,2,3])] 9 })
1 #write的时候关联字段如何写值 2 #One2many、Many2many更新记录值时和create一样,它的值是一个list,list每个对象是元组 3 #(0,0,dict_val) 创建新的记录并关联 4 #(1,id,dict_val) 关联记录并更新指定的id记录 5 #(2,id) 解除关联,并删除关联记录 6 #(3,id) 解除关联,并不删除关联记录 7 #(4,id) 与已存在关联表记录的id进行关联 8 #(5,) 解除所有关联 9 #(6,0,id_list) 解除原有的关联,替换成与id_list关联
注意事项:最好所有的更新不要直接写sql语句去更新值,因为odoo充分的利用了缓存,一搞不好你的数据就不同步了。比如你写sql语句更新了用户的权限,然而你使用的时候发现权限并没有生效,直到你重启服务后才会生效;这是因为权限对于odoo来说是访问量最大的一部分数据,所以它会直接读取缓存数据从而加快读取速度,因此如果你需要修改的用户权限立即生效的话就必须使用write去更新记录。并且最好前端刷新界面。