Uso de este tipo de campos
En Odoo se crean este tipo de campos para relacionar 2 modelos y según la nominalidad de dichas relaciones es que se definen este tipo de campos
Ejemplos prácticos de uso cotidiano
Campos Many2one
Este tipo de campos se lo utiliza para representar una clave foranea en un modelo. La nominalidad de este campo es que el modelo base tiene múltiples registros apuntando a un solo registro del modelo relacionado. Por ejemplo puedo tener en los clientes un comercial, vendedor o representante. Con lo cual tengo un campo en mis clientes apuntando a un solo vendedor.
Campos One2Many
Este caso se puede ver claramente en el detalle de facturas en donde la cabecera de la factura, que es un solo registro está relacionado con los ítems, los cuales pueden ser múltiples registros para una sola factura
Campos Many2Many
Estos dos modelos se relacionan de múltiples registros de un modelo a múltiples registros en el otro. Por ejemplo si tengo categorías en mis productos, esto me permite tener en un artículo varias categorías y en una categoría varios artículos, con lo cual Odoo usa una tabla intermedia en Postgres para poder relacionarlos y el ORM nos abstrae de esa capa de tener que administrar la capa intermedia
Sintaxis para definir los campos
#defino en un modelo un campo que cada registro se relaciona con una moneda
currency_id = fields.Many2one("res.currency")
#defino en un modelo la relación con líneas de detalle que van a tener
#en el modelo líneas de detalle habrá un campo many2one hacia la cabecera
line_ids = fields.One2many(comodel_name="stock.picking.line", inverse_name="picking_id",string='Lineas de ingreso')
#defino entre 2 modelos la relación many2many el campo tags_ids
#vinculando con el modelo tag_id, una table intermedia sa_mov_sa_tag_rel (nombre opcional)
#poniendo los nombres de los campos que van a relacionar los 2 modelos (nombre opcional)
tag_ids = fields.Many2many(
"sa.tag", "sa_mov_sa_tag_rel", "move_id", "tag_id")
Vistas
Al poner en una vista el campo many2one, en la vista se observa el name del campo relacionado. Al poner el many2many o el one2many se crea un detalle para agregar líneas y editar, crear. Para en un many2many que ponga burbujas para seleccionar la tabla relacionada se pone el widget many2many_tags y después se ponen los atributos para poner si quiero poder crear, poder editar, creación rápida o no. Dependiendo de la necesidad del momento. Como se puede ver en el Blog
Manipular campos One2many y Many2many comandos
mov = self.env["sa.movimiento"] #(se puede poner en una variable el modelo)
mov.browse(1).tag_ids #(muestra objeto de modelo sa.tag con todos los ids que tiene id=1 de sa.movimiento (sa.tag(1, 2, 4, 5))
#Modificación de registros
#Agregar nueva etiqueta y asignarlo al registro de movimientos
mov.browse(1).write({'tag_ids':[(0,0,{'name':'Nuevo Tag'})]})
#Al id=1 de movimientos, le agrega “Nuevo Tag” y lo crea en etiquetas o tag
#Corregir el nombre de un registro de etiquetas
mov.browse(1).write({'tag_ids':[(1,9,{'name':'Nuevo Tag corregido'})]})
#Al id cualquiera corregir el nombre de la tabla etiqueta o tag de id=9
#Borrar una etiqueta y sacarla de todos los registros de movimientos
mov.browse(1).write({'tag_ids':[(2,9,0)]})
#Al id cualquiera borrar la etiqueta id=9
#Sacar la relación de una Etiqueta a un Movimiento sin eliminarlo
mov.browse(1).write({'tag_ids':[(3,1,0)]})
#Al id 1 le saco la etiqueta de id=1
#Agregar una relación a un registro
mov.browse(1).write({'tag_ids':[(4,1,0)]})
#Al id 1 de movimientos le agrego el id 1 de etiquetas o tag
#Saca todas las relaciones de un Movimiento sin eliminar las etiquetas
mov.browse(1).write({'tag_ids':[(5,0,0)]})
#Al id 1 de movimiento le saca todas las etiquetas
#Poner relaciones de Etiquetas a un movimiento
mov.browse(1).write({'tag_ids':[(6,0,[1,3,5,7])]})
#Al id 1 de movimiento le pone las etiquetas 1,3,5 y 7 y si tenía otras, las saca
Este tema no termina aquí, será para el siguiente blog, como se recorren los campos 2many, como editar en vista tree o formularios mas complejos, etc.