Manipulation des enregistrements des modèles Partie 3 Sur 3

Introduction

Shell python d'Odoo

Nous avons vu, à travers les deux parties précédentes, l’importance et la puissance de pouvoir manipuler n’importe quel model de notre base de données relative à l’instance Odoo en Cours.
Dans cette troisième et dernière partie, nous allons découvrir les trois opérations populaires et indispensable à savoir le filtrage, le trie (sortage), ainsi que le mapping (listage) qui peuvent être effectué sur n’importe quel ensemble d’enregistrements.
Nous verrons aussi comment faire la composition des enregistrements d’un même modèle, avec des exemples concrets afin de bien assimiler les concepts évoqués sur cette troisième et dernière partie.
 
Rappel : pour accéder au terminal python d’Odoo exécutez la commande suivante sur le shell d’Ubuntu (Vous pouvez consulter l’article précédent pour plus de détailles). 
~$ ./cd odoo
~odoo$ ./odoo-bin shell -d  VotreBaseDeDonnees

Fonctions courantes sur les enregistrements :  

Durant notre manipulation des enregistrements, nous aurons besoin de trois opérations très utilisées dans les applications d’Odoo par défaut.
De même pour créer ces propres applications, nous aurons surement besoin d’utiliser ces trois aopérations qui sont , mapped, filtered et sorted.
Dans ce qui suit nous allons expliqué avec des exemples ces trois opérations. 

La Fonction Filtered

La fonction filtrage permet de renvoyer, des enregistrements qui répondent à des conditions d’une fonction. (Elle permet de ne garder que les éléments qui remplissent la condition)
Cette fonction prend comme paramètres des champs, d’un modèle, pour les inclure dans des expressions, qui entrent dans le filtrage des enregistrements du modèle en cours.

Exemple :

Si on souhaite par exemple, uniquement les clients qui sont des entreprises, on procède comme suit :
>>> clients=self.env['res.partner'].search([])
>>> clients
res.partner(14, 26, 33, 27, 10, 35, 18, 19, 11, 20, 22, 31, 23, 15, 34, 12, 21, 25, 37, 24, 36, 30, 38, 13, 29, 28, 9, 17, 32, 16, 1, 39, 40, 8, 7, 3)
>>> conDcompanies=lambda r: r.is_company
>>> companies=clients.filtered(conDcompanies)
>>> for r in companies:
...     print(r.name,r.is_company)
...
Azure Interior True
Deco Addict True
Gemini Furniture True
Lumber Inc True
Ready Mat True
The Jackson Group True
Wood Corner True
YourCompany True

La fonction mapped : 

La fonction mapped, prend comme paramètre des textes au lieu d’une fonction. Elle permet de d’énumérer, de lister ou d’afficher les enregistrements selon, le nom ou les noms des enregistrements passés comme paramètres.
 Exemple :
Si on souhaite afficher les clients selon l’enregistrement Nom, on procède comme suit :
>>> clients=self.env['res.partner'].search([])
>>> clientsbyName=clients.mapped('name')
>>> clientsbyName
['Azure Interior', 'Brandon Freeman', 'Colleen Diaz', 'Nicole Ford', 'Deco Addict', 'Addison Olson', 'Douglas Fletcher', 'Floyd Steward', 'Gemini Furniture', 'Edwin Hansen', 'Jesse Brown', 'Oscar Morgan', 'Soham Palmer', 'Lumber Inc', 'Lorraine Douglas', 'Ready Mat', 'Billy Fox', 'Edith Sanchez', 'Julie Richards', 'Kim Snyder', 'Sandra Neal', 'Theodore Gardner', 'Travis Mendoza', 'The Jackson Group', 'Gordon Owens', 'Toni Rhodes', 'Wood Corner', 'Ron Gibson', 'Tom Ruiz', 'Willie Burke', 'YourCompany', 'Chester Reed', 'Dwayne Newman', 'Joel Willis', 'Marc Demo', 'Mitchell Admin']
 
 C’est possible aussi d’afficher les noms, email et adresse des partenaires.
Pour se faire, et pour ne pas avoir une longue liste, on peut effectuer tout d’abord un filtrage pour afficher uniquement les parternaires  entreprises (comme précédemment), puis on fait un mappage sur le résultat :
>>> conDcompanies=lambda r: r.is_company
>>> companies=clients.filtered(conDcompanies)
>>> clientsbyNameEmailStreet=companies.mapped(lambda r:(r.name,r.email,r.street))
>>> clientsbyNameEmailStreet
[('Azure Interior', 'vauxoo@yourcompany.example.com', '4557 De Silva St'), ('Deco Addict', 'info@agrolait.com', '77 Santa Barbara Rd'), ('Gemini Furniture', 'john.b@tech.info', '317 Fairchild Dr'), ('Lumber Inc', 'lumber-inv92@example.com', '1337 N San Joaquin St'), ('Ready Mat', 'info@deltapc.com', '7500 W Linne Road'), ('The Jackson Group', 'jackson.group82@example.com', '1611 Peony Dr'), ('Wood Corner', 'bhu.a100@ic.example.com', '1839 Arbor Way'), ('YourCompany', 'info@yourcompany.com', '250 Executive Park Blvd, Suite 3400')]

La Fonction Sorted:

La fonction sorted,  prend comme paramètre une clé (key) qui sera un des champs du modèle en cours, et va retourner un ensemble d’enregistrements classés avec ordre croissant  par défaut, sur le champ donné comme clé d’ordre.
C’est possible aussi, d’afficher les enregistrements par ordre décroissant, en ajoutant simplement le paramètre reverse=True.
Exemple :
Si On souhaite afficher les partenaires selon leurs noms par ordre croissant, on procède comme suit :
>>> clients=self.env['res.partner'].search([])
>>> clientsByOrder=clients.sorted(key='name')
>>> clientsByOrder
res.partner(35, 14, 21, 26, 39, 33, 10, 18, 40, 25, 20, 19, 11, 29, 22, 8, 37, 24, 34, 15, 7, 3, 27, 31, 12, 17, 36, 23, 13, 30, 32, 28, 38, 16, 9, 1)
>>> clientsbyName=clientsByOrder.mapped('name')
 # Ici nous avons utilisé la fonction mapped  pour afficher les noms des clients
>>> clientsbyName
['Addison Olson', 'Azure Interior', 'Billy Fox', 'Brandon Freeman', 'Chester Reed', 'Colleen Diaz', 'Deco Addict', 'Douglas Fletcher', 'Dwayne Newman', 'Edith Sanchez', 'Edwin Hansen', 'Floyd Steward', 'Gemini Furniture', 'Gordon Owens', 'Jesse Brown', 'Joel Willis', 'Julie Richards', 'Kim Snyder', 'Lorraine Douglas', 'Lumber Inc', 'Marc Demo', 'Mitchell Admin', 'Nicole Ford', 'Oscar Morgan', 'Ready Mat', 'Ron Gibson', 'Sandra Neal', 'Soham Palmer', 'The Jackson Group', 'Theodore Gardner', 'Tom Ruiz', 'Toni Rhodes', 'Travis Mendoza', 'Willie Burke', 'Wood Corner', 'YourCompany']
 
Maintenant Si On souhaite afficher les partenaires selon leurs noms par ordre décroissant, il faut juste ajouter le paramètre reverse=True de la manière suivante :
>>> clientsByOrder=clients.sorted(key='name',reverse=True)
>>> clientsbyName=clientsByOrder.mapped('name')
>>> clientsbyName
['YourCompany', 'Wood Corner', 'Willie Burke', 'Travis Mendoza', 'Toni Rhodes', 'Tom Ruiz', 'Theodore Gardner', 'The Jackson Group', 'Soham Palmer', 'Sandra Neal', 'Ron Gibson', 'Ready Mat', 'Oscar Morgan', 'Nicole Ford', 'Mitchell Admin', 'Marc Demo', 'Lumber Inc', 'Lorraine Douglas', 'Kim Snyder', 'Julie Richards', 'Joel Willis', 'Jesse Brown', 'Gordon Owens', 'Gemini Furniture', 'Floyd Steward', 'Edwin Hansen', 'Edith Sanchez', 'Dwayne Newman', 'Douglas Fletcher', 'Deco Addict', 'Colleen Diaz', 'Chester Reed', 'Brandon Freeman', 'Billy Fox', 'Azure Interior', 'Addison Olson']

Composition d'enregistrements : 

Il est très souvent utile de pouvoir composer plusieurs enregistrements, afin de pouvoir effectuer des opérations sur les enregistrements.
La composition des enregistrements du même modèle se fait par les différents opérateurs, comme les opérateurs suivants :  (On veut dire par Rs  Record Set (un ensemble d’enregistrements))

  • Rs1 + Rs2 : le résultat de cette opération, est un nouvel ensemble d’enregistrements qui contient les enregistrements de Rs1 suivi par les enregistrements de Rs2, avec la possibilité d’avoir des enregistrements dupliqués.
  • Rs1 - Rs2 : le résultat de cette opération est un ensemble d’enregistrements qui appartiennent à Rs1 et n’appartiennent pas à Rs2, avec la préservation de l’ordre
  • Rs1 & Rs2 : cette opération revoie un ensemble d’enregistrements qui contient les enregistrements qui appartiennent à la fois à Rs1 et Rs2.  L’ordre ici n’est pas préservé mais il n’y a pas de duplication de données.
  • Rs1 | Rs2 : le résultat de cette opération est un ensemble d’enregistrements composés de l’union de Rs1 et Rs2, ou d’une autre façon qui appartiennent à Rs1 ou à Rs2 . L’ordre n’est pas préservé mais il n’y pas de redondances
  • Rs1 == Rs2 : Vrai si Rs1 et Rs2 contiennent les mêmes enregistrements
  • Rs1 <= Rs2 (Rs1 < Rs2) : Vrai si tous les enregistrements de Rs1 sont inclus dans Rs2. C.-à-d. Rs1 est un sous ensemble de Rs2 .
  • Rs1 >= Rs2 (Rs1 > Rs2) :  C’est l’inverse de l’opération précédente, elle est Vrai si les enregistrements de Rs1 inclus les enregistrements de Rs2. C.-à-d. Rs1 est un super ensemble de Rs2.
  • Rs1 ! Rs2 : vrai si Rs1 et Rs2 ne contiennent pas les mêmes enregistrements.
  • R1 in Rs2 : vrai si R1 (un seul enregistrement) fait partie de Rs2
  • R1 not in Rs2 : vrai si R1 (un seul enregistrement) ne fait pas partie de Rs2.

Exemples pratiques :
Dans ce qui vient, des exemples pratiques pour bien comprendre la composition entre les enregistrements, toujours en se basant sur el modèle res.partner  :

  • RS1 : On met dans cet ensemble les partenaires qui sont des entreprises :

RS1=self.env['res.partner'].search([('is_company','=',True)])
>>> RS1.mapped('name')
['Azure Interior', 'Deco Addict', 'Gemini Furniture', 'Lumber Inc', 'Ready Mat', 'The Jackson Group', 'Wood Corner', 'YourCompany']

  • RS2 : Les partenaires dont le nom contient ‘y’ :

>>> RS2=self.env['res.partner'].search([('name','like','y')])
>>> RS2.mapped('name')
['Floyd Steward', 'Ready Mat', 'Billy Fox', 'Kim Snyder', 'YourCompany', 'Dwayne Newman']

  • On teste maintenant les différentes opérations :

>>> R=(RS1+RS2).mapped('name')   
>>> R
['Azure Interior', 'Deco Addict', 'Gemini Furniture', 'Lumber Inc', 'Ready Mat', 'The Jackson Group', 'Wood Corner', 'YourCompany', 'Floyd Steward', 'Ready Mat', 'Billy Fox', 'Kim Snyder', 'YourCompany', 'Dwayne Newman']
>>> R=(RS1|RS2).mapped('name')
>>> R
['Azure Interior', 'Deco Addict', 'Gemini Furniture', 'Lumber Inc', 'Ready Mat', 'The Jackson Group', 'Wood Corner', 'YourCompany', 'Floyd Steward', 'Billy Fox', 'Kim Snyder', 'Dwayne Newman']
>>> R=(RS1-RS2).mapped('name')
>>> R
['Azure Interior', 'Deco Addict', 'Gemini Furniture', 'Lumber Inc', 'The Jackson Group', 'Wood Corner']
>>> R=(RS1&RS2).mapped('name')
>>> R
['Ready Mat', 'YourCompany']

  En se basant sur ces exemples vous pouvez tester vous-même les autres opérations 

Autres Opérations : 

En plus des opérations cités, d’autres opérations sont possibles, citons par exemple :
  • Rs[0] renvoie le premier enregistrement de l’ensemble d’opérations Rs (RecordSet), de même pour extraire l’enregistrement i, on met tout simplement Rs[i].
  • Rs[-1] renvoie le dernier  enregistrement de l’ensemble d’opérations Rs (RecordSet)
  • Rs[1 :] : permet de renvoyer une Copie des enregistrements de Rs, sans le premier enregistrement, de même pour extraire les éléments à partir de l’enregistrement i, on met Rs[i :] (exemple Rs[12 :], va renvoyer les enregistrements à partir de l’enregistrement i  
  • Rs[ : i ] , inversement à l’élément précédent, va renvoyer les enregistrements en partant du premier enregistrement jusqu’à l’enregistrement i
  • RS |= R1 , où R1 est un enregistrement de même type que RS, permet d’ajouter l’enregistrement RA à RS (un ensemble d’enregistrements) , si cet enregistrement n’existe pas dans  RS.
  • RS += R1 , où R1 est un enregistrement de même type que RS, ressemble à l’opération précédente, permet donc d’ajouter l’enregistrement RA à RS , mais ici l’enregistrement sera ajouté  malgré qu’il existe  dans RS (il sera dupliqué)
  • RS -=R1, permet de retirer l’enregistrement R1 de l’ensemble RS si cela existe dans RS
Exemples pratiques :
  • Dans ces exemples, nous allons tester quelques opérations précédentes pour comprendre le principe, vous pouvez ensuite s’exercer avec d’autres exemples de votre choix.  
  •  Pour démarrer on reprend l’exemple précédent pour RS1 et RS2 de cette phaçon:
>>> RS1=self.env['res.partner'].search([('is_company','=',True)])
>>> RS1
res.partner(14, 10, 11, 15, 12, 13, 9, 1)
>>> RS2=self.env['res.partner'].search([('name','like','y')])
>>> RS2
res.partner(19, 12, 21, 24, 1, 40)
>>> p1=RS1[:4]
>>> p1
res.partner(14, 10, 11, 15)
>>> p2=RS1[4:]
>>> p2
res.partner(12, 13, 9, 1)
>>> p3=RS1[3]
>>> p3
res.partner(15,)
>>> RS2|=p3
>>> RS2
res.partner(19, 12, 21, 24, 1, 40, 15)
>>> RS2+=p3
>>> RS2
res.partner(19, 12, 21, 24, 1, 40, 15, 15)
>>> RS2-=p3
>>> RS2
res.partner(19, 12, 21, 24, 1, 40)

Conclusion :

Dans cette troisième et dernière partie de l’article consacré à la manipulation des enregistrements, nous avons découvert les opérations mapping, filtering et sortage , qui peuvent êtres effectués sur  des modèles, ainsi que la composition des enregistrements.
Tout au long de cet article, nous avons évoqués des concepts clés pour bien comprendre comment manipuler les enregistrements d’un modèle, et ainsi créer ou étendre des applications Odoo plus facilement. 

Télécharger gratuitement votre  guide odoo ! 

Télécharger Gratuitement votre guide Odoo

Découvrez comment , Odoo  est une vraie opportunité pour les entreprises et les développeurs !


Télécharger !