Manipulation des enregistrements des modèles Partie 1 Sur 3

Introduction

Shell python d'Odoo

Nous avons vu dans les articles précédents, comment créer des modèles et des relations avec ces modèles.
Nous avons également, travailler sur les enregistrements d’un modèle, en utilisant le mot self qui fait référence au modèle en cours, mais cela ne va pas fonctionner si on souhaite accéder à des enregistrements d’un autre modèle.
Dans les différentes parties de cet article, nous allons se concentrer sur patrie très importante, et qu’on sera amené à travailler avec, dans nos applications Odoo, qui est la manipulation des enregistrements, en utilisant la classe d’environnement, avec les différentes possibilités qu’elle offre.
En fait, Odoo dans son propre Framework, utilise l’ORM (Object Relational Mapping) qui nous offre des API (Application Programing Interface),qui facilite l’interfaçage avec notre base de données, à travers les opérations de base (CRUD Create, Read, Update, Delete) mais aussi d’autres opérations.
Nous allons donc, dans un premier temps comprendre l’environnement d’exécution, puis nous continuons notre découverte sur les opérations de requêtes, de création, de lecture, de modification, de copie et de suppression des enregistrements, ainsi que d’autres opérations.

Méthode suivie pour les tests et démonstrations de cet article : 

 Contrairement à ce qu’on a l’habitude de faire durant les articles précédents, pour tester les concepts étudiés, dont lesquels nous avons utilisé l’IDE Pycharm, dans cet article nous allons utiliser les commandes à travers le Shell python d’Odoo, qui va nous permettre de mieux tester et cerner les concepts évoqués dans cet article.  
Mais avant de lancer les commandes, assurez vous que le module contact est installé, et que les données de démonstrations sont chargées lors de l’installation de la base de données Odoo, puisqu’elles sont des bons exemples pour la compréhension des concepts de cet articles.
Comme pyhton, Odoo a son propre shell de commandes qui sert à exécuter et tester directement les commandes python dans notre instance Odoo encours.
Pour ouvrir le shell des commandes Odoo, ouvrir en premier lieu le shell d’Ubuntu, puis positionnez-vous sur le répertoire Odoo , puis exécuter la commande suivante :

~$ ./cd odoo
~odoo$ ./odoo-bin shell -d  VotreBaseDeDonnees

Où : VotreBaseDeDonnees est le nom de votre base de données que vous souhaitez travailler avec.
Astuce : Si vous ne connaissez pas le nom de votre base de données, vous pouvez simplement activez le mode développeur d’Odoo, en haut à droite vous pouvez connaitre le nom exact de la base de données en cours.
 Après l’exécution de cette commande, nous allons visualiser le shell de lancement d’Odoo usuel, puis à la fin, nous aurons le shell python d’Odoo qui attend nos commandes (>>>).

Nom de la base de données en cours

L’environnement d’exécution d’Odoo : 

Si vous remarquez bien, vous aurez à la fin de l’exécution de la commande précédente, entre autres informations, un variable nommé env, issu de la classe odoo.api.Environment , le répertoire de lancement du  module Odoo, à partir du fichier __init__ et le mot self qui pointe vers l’utilisateur en cours.
Déjà à partir de là, nous pouvons avoir une idée sur l’environnement d’exécution, en fait, dès le lancement d’Odoo, il va charger toutes les informations des modules dans une registre centralisé, enregistré dans la classe Environement.
Ces informations, sont accessible à travers le mot clé self, comme nous l’habitude de faire avec les modèles.
Comme premier exercice, tapez les commandes suivantes : Tapez les commandes suivantes :
>>> self
res.users(1,)
>>> self._name
'res.users'
>>> self.name
'OdooBot'
>>> self.login
'__system__'

Dans ces commandes, lorsqu’on tape la commande self, le système va nous renvoyer l’utilisateur issu du modèle res.users, dont l’id  (l’identifiant) égale à 1.
Le nom du modèle est obtenu en tapant self._name qui est res.users alors que le nom de l’utilisateur est obtenu en tapant self.name qui est OdooBot. 

Notion d’utilisateur superviseur : 

mode Superviseur

Il faut noter que l’utilisateur nommé OdooBot représente le superviseur qui a tous les droits d’accès, et nom l’administrateur qui est déplacé sur l’Id N° 2.
Pour utiliser les droits de l’utilisateur superviseur, il faut activer le mode développeur, puis cliquer sur l’icône insecte qui représente le mode développeur, ensuite sélectionner l’option devenir supervisuer, la bande jaune sera affichée en haut sur l’espace de l’utilisateur, et l’utilisateur sera nommé OdooBot.
Cette option de superviseur est apparue à partir de la version 12 d’Odoo, pour limiter les risques en ayant tous les droits d’accès, surtout en mode multi-entreprises, et de n’utiliser le superviseur que lorsqu’on est sûr de ce qu’on veut faire.    

 Les attributs de l’environnement d’exécution d’Odoo : 

Pour afficher l’environnement en cours tapez la commande :
>>> self.env
< odoo.api.Environment object at 0x7fc4e0e83820>

L’attribut env de n’importe quel enregistrement, valable sous la désignation self.env, est une instance de la classe Environment définit dans le module odoo.api.
La classe Environement joue un rôle primordial, dans le développent des applications Odoo, en effet :

  •  Elle permet d’accéder au registre central dans tous les modèles sont valable. Il suffit d’avoir le nom du modèle pour pouvoir manipuler ces enregistrements. Par exemple si on utilise la commande : self.env['res.partner'] renvoie un référence sur res.partner avec un enregistrement vide.  On peut par la suite utiliser les méthodes search() ou browse() pour obtenir des enregistrements  sur ce modèle.
  • Elle contient l’attribut env.cr , qui est le curseur sur  la base de données qui permet de passer des requêtes SQL
  • Elle a l’attribut env.user , qui pointe vers l’utilisateur courant  
  • Elle a l’attribut env.uid , qui pointe vers l’identifiant de l’utilisateur courant, pareil à écrire env.user.id
  • Elle a l’attribut context , qui renvoie un dictionnaire contenant des informations sur le contexte de l’appel.  Cela inclus des informations sur la langue utilisée par l’utilisateur, l’ID de l’utilisateur encours, le fuseau horaire, la sélection actuelle des enregistrements, ainsi que d’autres informations.

Obtention de la liste de tous les enregistrements d’un autre modèle :

En utilisant slef dans la session en cours, on obtient des enregistrements du modèle en cours.
Pour obtenir des enregistrements d’un autre modèle, on doit utiliser l’expression self.env['nomdumodele'] .
Comme exemple : tapez les commandes suivantes, les explications sont en dessus de chaque commande : 

>>> model_partner=self.env['res.partner']
>>> print(model_partner)
>>> res.partner()

Cette commande va obtenir une référence sur le modèle res.partner, et renvoie un enregistrement vide res.partner().
Pour obtenir la liste de tous les enregistrements, utilisez la commande search() avec une liste vide de la manière suivante :

>>> model_partner=self.env['res.partner']
>>> all_rec_model_partner=model_partner.search([],order='id')
>>> print(all_rec_model_partner)
>>> res.partner(1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
32,33,34,35,36,37,38,39,40,64,65,66,67)

Dans la première ligne nous avons obtenu la référence du modèle res.patner, et nous l’avons affecté au variable model_partner qui est un enregistrement vide.
Dans la deuxième ligne, nous affectons tous les enregistrement du modèle res.partner  au variable all_rec_model_partner , avec l’option (order=’id’) pour les afficher par ordre croissant sur le champ ’id’.
Dans la troisième commande nous avons imprimé tous les enregistrements du modèle res.partner, en renvoyant une liste par ordre croissants de leur id.  

Explorer des enregistrements dont on sait leur id : 

Dans le cas où on connaisse l’id (l’identifiant) de l’enregistrement ou des enregistrements, on peut explorer leur contenu en utilisant la fonction browse(), comme le montre les  exemples suivants:

>>> br_record=model_partner.browse(32)
>>> print(br_record.name)
Tom Ruis
>>>  br_records=model_partner.browse([15,19,32])
>>>  for r in br_records :
….           Print(r.name)
…..
Lumber Inc
Floyd Steward
Tom Ruiz

Dans la première ligne, nous avons exploré l’enregistrement qui porte l’id 32, puis nous avons imprimé son nom.  
Dans la deuxième commande, nous avons exploré une liste de trois id  [15,19,32].
Contrairement à la première commande, pour afficher leur nom il fallait faire une boucle sur tous les enregistrements.

Utilisation des expressions de domaines pour rechercher les enregistrements : 

Dans la section afficher tous les enregistrements nous avons accédé à un modèle, à travers self.env, puis afficher tous ces enregistrements.
Dans cette partie, nous allons utiliser les expressions de domaines pour accéder aux enregistrements qui remplissent les conditions des expressions de domaines.
Cela est possible en utilisant la méthode search() qui prend un domaine et renvoie les enregistrements qui entre dans le cadre des conditions du domaine.
 
Remarque : la méthode search, inclut une condition implicite qui dit que les enregistrements doivent être actifs (active=True) , ce qui implique que les enregistrements inactifs ne seront pas affichés.
 
D’autres paramètres, peuvent être ajoutés à la méthode search :

  • order : exemple order=’name’, ou or=’id’, précise l’affichage par ordre croissant sur le champ sélectionné. Pour les afficher dans l’ordre décroissant ajouter le mot clé DESC
  • limit : pour limier ne nombre d’enregistrements affichés
  • offset : ignore les n premiers enregistrements
  • count : un booléen, s’il est Vrai, la méthode renvoie le nombre d’enregistrements au lieu de la liste des enregistrements.

Remarque :  Afin de calculer le nombre d’enregistrements, il est préférable d’utiliser la méthode search_count(damain) qui est plus claire que l’expression search(domain, count=True).
Les deux méthodes renvoient le même résultat, qui est le nombre d’enregistrements. 

Les expressions des domaines : 

Expression de domaine

Afin d’obtenir les enregistrements souhaités, à partir d’un modèle, on suit les étapes :

  • Obtenir la référence du modèle souhaité, et de l’affecter à une variable :
    • model_respartner=self.env['res.patner']
  • Définir un domaine de recherche en utilisant les expressions de domaines :
    • domain=[expression]
  • Obtenir le résultat souhaité :
    • respartner=model_resparnter.serarch(domain)

 
Dans l’exemple précédent, le variable domain représente une expression de domaine, qui est une liste contenant de conditions.
Chaque condition est un tuple qui suit la forme : ( 'nom_du_champ', 'operateur', 'valeur ').

Où :

  • nom_du_champ : c’est le champ qu’on va appliquer le filtre, il peut être un champs obtenu avec l’utilisation du point (res.partner .company_id par exemple)
  • operateur : peut être l’un des choix suivants :
    • Les opérations usuelles : =,> ,<, < =, >=, != et <>
    • in, not in : pour vérifier si la valeur est dans l’intervalle ou pas.  La valeur doit être donc une liste, même si elle ne contient qu’une valeur. ([2,9,90]) ou ([2])
    • ’like’  et  ’not like’ : vérifie est ce que le champs recherché contient ou ne contient la valeur indiquée, la recherche n’est pas sensible à la casse.
    • ’ilike’  et  ’not ilike’ : comme la précédente, sauf qu’ici, la recherche est sensible à la casse 
    • ’=like’, ’=ilike’ : ces deux opérateurs sont utilisés pour revérifier que la valeur recherchée vérifie une certaine syntaxe, par exemple si on souhaite rechercher les noms qui commence par AB, on met  ’AB% ’, ou pour chercher les noms qui contient ’aBc’ on met ’%aBc%’
    • ’chaild of’ : renvoi les valeurs enfants dans une relation de hiérarchie
  •  valeur : est la valeur que doit vérifier la condition en cours, elle peut être un entier, un décimal, un booléen, un texte ou des listes. Elle peut contenir aussi des champs et des valeurs de contexte. 

Un domaine peut contenir une seule condition comme montré dans l’exemple suivant :

 >>> model_partner=self.env['res.partner']
>>> domain=[('name', 'like', 'A']
>>>  res_partner=model_partner.search(domain)
>>>  for r in res_partner :
….           Print(r.name)
…..
Azure Interior
Decco Addict
Addisson Olson
FOUAD
Michell Admin

 
Dance cet semple, l’expression du domaine contient une seul condition simple qui est obtenir les enregistrements du modèle res.partner dont le nom Contient ’A’ , le résultat de l’application de ce domaine est 5 enregistrements.

Le domaine peut contenir aussi, une combinaison de plusieurs conditions, séparées par des virgules, par exemple si on souhaite afficher uniquement les contacts qui sont des entreprises et leur email est renseigné, on doit écrire dans le domaine l’expression suivante : 

>>> domain=[('is_company', '=',True), ('email', '!=',False)]

Si aucune opération n’est définie entre les conditions, l’opération ’&’ est utilisée par défaut qui veut dire qu’il faut satisfaire toutes les conditions citées, entre les virgules.
D’autres expressions plus complexes, peuvent être définit, en utilisant les opérateurs explicitement, à savoir l’opérateur ’&’ qui représente ‘ET’ et l’opérateur ’|’ qui représente ’OU’.
 Dans ces cas, les opérations sont concaténées et évaluées d’une manière récursive.
Dans l’exemple suivant :

Domain=
['&',
('is_company', '=',True)
'|',
'!',( 'email', '=',False) ,
'!', ('phone', '=',False)
]

Dans cette expression on veut obtenir tous les contacts, de tel sorte que le partenaire soit une entreprise, et que son email ou son n° de téléphone soit renseigné (n’est pas vide où ! False).
Les opérations '|' ou OR et  '&' ou ET, sont des opérateurs binaires , alors que l’opérateur '!'  qui signifie la négation, est une opération unaire et  doit être placé, juste avant la condition, comme dans notre exemple :  '!',( 'email', '=',False)  signifie la négation de l’email n’est pas renseigné.
Pour une représentation plus formelle, on commence plutôt, par les opérateurs que par les opérandes, on appelle cette présentation Polish notation.
Maintenant pour obtenir le même résultat que l’expression précédente, en utilisant la notation
Polish, on doit écrire le domaine suivant :
Domain=
['&', '|',
'!',( 'email', '=',False) ,
'!', ('phone', '=',False),
('is_company', '=',True)
]

Comme nous l’avons indiqué précédemment l’expression va être traitée d’une manière récursive, on commence par l’opérateur ’|’ pour obtenir les contacts qui ont un email ou un numéro de téléphone, puis on vérifie sur le résultat que le ces contacts sont des entreprises. 

Conclusion :

Dans cette première partie, nous avons fait une introduction sur un concept indispensable, que les développeurs Odoo vont rencontrer souvent, qui est la manipulation des enregistrements des modèles.
Nous avons donc expliqué le rôle de la classe environnement, qui contient les informations nécessaires pour accéder à n’importe quel modèle, et d’autres informations sur l’utilisateur en cours et le contexte incluant la langue, le fuseau horaire, etc.  
Nous avons aussi vu comment obtenir une référence vers n’importe quel modèle de l’instance en cours, pour pouvoir accéder à tous ces enregistrements où à des enregistrements qui remplissent des conditions bien précis à travers l’utilisation des expressions de domaine.
Dans la deuxième partie, nous continuons notre découverte sur différentes les opérations de base qu’on peut effectuer sur les modèles de l’instance Odoo en cours d’exécution. 

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 !