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 #Many2many 21 author_ids = fields.Many2many('res.partner', string='Authors') 22 23 parent_path = fields.Char(index=True) 24 25 @api.constrains('parent_id') 26 def _check_hierarchy(self): 27 if not self.parent_id._check_recursion():#因為主從都是自己表記錄,所以這里要防止出現遞歸 28 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 #Many2one、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去更新記錄。並且最好前端刷新界面。
