21. Desarrollando con Odoo (16). Self.env.search con mas detalle. Ejemplo de buscar los menús que puede acceder un usuario

 Ya se habló un poco en una entrada anterior. En principio se utiliza para buscar objetos en el ORM.

Veamos algunos ejemplos:

1. Búsqueda simple, ordenación, limitación de número de registros y saltarse algunos

Veamos algunas búsquedas sobre el modelo res.groups que se guarda en la tabla res_groups:

#1. Buscar todos los registros
#   SELECT * FROM res_groups
groups=self.env['res.groups'].search([])

#2. Buscar por un campo. El operador puede ser '=', '>', '<', '<=', '>=' ....
#   SELECT * FROM res_groups WHERE id='1'
groups=self.env['res.groups'].search(['id','=','1'])

#3. Busqueda con "LIKE". OJO! No se pone el %
#   SELECT * FROM res_groups WHERE name LIKE 'Admin%' 
groups=self.env['res.groups'].search(['name','like','Admin'])

#4. Varias condiciones con AND. Se separan con una coma
#   SELECT * FROM res_groups WHERE id>'1' AND name LIKE 'Other%'
groups=self.env['res.groups'].search([('id','>','1'), ('name','like','Other')])

#5. Varias condiciones con OR. Igual que antes se separan con una coma, pero se antepone '|'
#   SELECT * FROM res_groups WHERE id>'1' OR name LIKE 'Other%'
groups=self.env['res.groups'].search(['|',('id','>','1'), ('name','like','Other')])

#6. Ordenar los registros de búsqueda
#   SELECT * FROM res_groups ORDER BY name, id
groups=self.env['res.groups'].search([], order='name, id')

#7. Ordenar descendentemente los registros de búsqueda
#   SELECT * FROM res_groups ORDER BY name DESC, id
groups=self.env['res.groups'].search([], order='name desc, id')

#8. Limitar el número de registros de búsqueda y saltarse varios registros
#   SELECT * FROM res_groups LIMIT 10 OFFSET=5
groups=self.env['res.groups'].search([], limit=10, offset=5)

#9. Cláusula IN. Se puede usar list [] o tupla ()
#   SELECT * FROM res_groups WHERE id IN (1,3,4,5)
groups=self.env['res.groups'].search([('id','in',[1,3,4,5])])
groups=self.env['res.groups'].search((('id','in',(1,3,4,5))])

#10. Cláusula NOT IN. Se puede usar list [] o tupla ()
#   SELECT * FROM res_groups WHERE id NOT IN (1,3,4,5)
groups=self.env['res.groups'].search([('id','not in',[1,3,4,5])])
groups=self.env['res.groups'].search((('id','not in',(1,3,4,5))])

2. Búsquedas en campos relacionados.

Veamos como se realizan las condiciones en base a los campos del objeto relacionado.

2.1 Campo many2one. Buscar por un campo del "padre"


Para un campo many2one como "category_id" que enlaza con el objeto "ir.module.category", se puede hacer una condición de este tipo "category_id.name" para buscar por el campo "name"


#1. Buscar por el nombre del objeto relacionado
#   SELECT A.* 
#   FROM res_groups A 
#   JOIN ir_module_category B 
#     ON  B.id=A.category_id
#     AND B.name='users' 
groups=self.env['res.groups'].search([('category_id.name','=','users')])

Si por algún motivo, no tuvieran nombre las categorías se puede igualar a False

#1. Buscar por el nombre del objeto relacionado
#   SELECT A.* 
#   FROM res_groups A 
#   JOIN ir_module_category B 
#     ON  B.id=A.category_id
#     AND B.name IS NULL
groups=self.env['res.groups'].search([('category_id.name','=',False)])

2.2 Campo many2many o many2one. Buscar los hijos del padre. ".ids"

Vamos a buscar los grupos "res.groups" (hijo) a los que pertenece un usuario "res.users" (padre) . El campo (del padre ) many2many es "groups_id". Pero utilizamos ".ids" para obtener todos los "id". Dado un registro "user", podemos buscar los grupos a los que pertenece.


groups=self.env['res.groups'].search([('id','in',user.groups_id.ids)])

 

2.2 Campo many2many o many2one. Buscar los registros (padre) que tengan un hijo identificado por su id. 

Vamos a buscar aquellos menus "ir.ui.menu" (padre)  a los que tienen acceso un grupo "res.groups" (hijo), sabiendo el id del grupo. El campo del padre tipo many2one es "groups_id". Supongamos que tengamos el registro "grupo" (hijo) con su campo "id" , para ello hacemos:


menus=self.env['ir.ui.menus'].search([('groups_id','in',[grupo.id])])

  OJO: El valor "grupo.id" es uns lista y por tanto va entre corchetes. La interpretación de esta sentencia es engañosa pues el orden de 'groups_id' y de [grupo.id] a simple vista podría dar lugar a que fuera al revés pues 'groups_id' és el conjunto padre que contiene los valores... pero la nomenclatura manda.


3. Ejemplo de búsqueda de menús que son directamente accesible por un usuario.

Este ejemplo voy a intentar completar el módulo hide_menu_user de Cybrosys , para ello descargamos el módulo, y en la clase HideMenuUser que hereda de "res.users" le añadimos un campo calculado "all_user_menus_ids"

@api.depends("groups_id")
def _get_all_user_menus(self):
    for record in self:
        menuSet=set(())
        lstGroupIds=record.groups_id.ids
        #Buscamos los grupos que pertenece el usuario
groups=self.env['res.groups'].search([('id', 'in', record.groups_id.ids)]) for group in groups:
            #Obtenenmos los menus que puede acceder ese grupo
menus=self.env["ir.ui.menu"].search([('groups_id', 'in', [group.id])]) for menu in menus: menuSet.add(menu.id) record.all_user_menus_ids = list(menuSet) all_user_menus_ids = fields.One2many(comodel_name='ir.ui.menu', compute="_get_all_user_menus", string='All user menus')




Comentarios

Entradas populares de este blog

20. Desarrollando con Odoo (15). Permisos y grupos. Crear usuarios de la aplicación. Restringir permisos a usuarios

2. El Modo desarrollador

8. Desarrollando con Odoo (6). Herencia de clase en modelos. Herencia de vistas. Operaciones numeradas en Odoo ??