La relation Hiérarchie entre les modèles
Introduction
Dans l’article précédent, nous avons étudier les trois types de relations entre les modèles différents. Dans plusieurs cas pratiques, nous aurons besoin de représenter la relation entre un modèle et lui-même, on crée à travers ce type de relation ce qu’on appelle une relation hiérarchique, ou les modèles imbriqués.
Un modèle imbriqué (nested model) , est un concept utilisé par les SGBRO (Système de gestion de base de données relationnel Objet), comme le cas avec le SGBDRO PostgreSQL qu’Odoo utilise par défaut, qui permet de représenter des structures de type complexe et d’étendre les fonctions de base d’une base de données relationnelle (SGBDR)
Le présent article, a pour objectif de pouvoir présenter un exemple courant qui est la catégorisation ou le typage d’un modèle, en créant une relation hiérarchie entre le modèle et lui-même.
Pour illustrer les concept nous allons utiliser notre modèle exemple ‘agence.vehicule’ pour définir les catégories des véhicules.
But d’utilisation d’une hiérarchie à un modèle :
C’est possible de présenter, une relation entre un modèle et lui-même, en utilisant une relation de type ManyToOne, mais en activant l’option des modèles imbriqués, nous aurons plus de fonctionnalités et de performances avec les requêtes engendrés par l’ORM Odoo.
L’exemple le plus courant, est la catégorisation ou la classification des modèles. Chaque catégorie peut avoir plusieurs autres sous catégories, et peut elle-même être une sous classe d’une autre catégorie.
L’autre exemple, est la composition ou la relation Composant/Composé. Un Composant peut être composé par plusieurs autres composants, et ainsi de suite.
Le non contrôle de ce type de relations peut engendrer le problème de récursion, et pour éviter ce type de problèmes Odoo dispose d’une fonction de vérification de non existence de récursion lors de l’ajout de nouveaux enregistrements.
Application à notre exemple Agence de Location de Véhicule :
Afin d’avoir une idée claire sur le concept hiérarchie des modèles, nous revenons à notre exemple Gestion de location de véhicules en lui ajoutant un autre modèle, qui permettra de gérer les catégories des véhicules.
1.Ajoutez le modèle agence.categorie.vehicule:
Dans le répertoire des modèles créer le fichier python et appelez le agence_categorie_vehicule.py, Puis mettez dedans le code suivant :
from odoo import models,fields,api
from odoo.exceptions import ValidationError
class AgenceCategVehicule(models.Model):
_name = 'agence.categorie.vehicule'
_description = 'Représentation des catégrories des véhicules'
_parent_store = True
_parent_name = "parent_id" # optional if field is 'parent_id'
parent_path = fields.Char(index=True)
name=fields.Char('Catégorie')
parent_id=fields.Many2one(
'agence.categorie.vehicule',
ondelete='restrict',
string='Catégorie Mère',
Index=True
)
child_ids = fields.One2many(
'agence.categorie.vehicule',
'parent_id',
ondelete='restrict',
string='Sous-Catégorie ,
Index=True
)
@api.constrains('parent_id')
def _check_hierarchy(self):
if not self._check_recursion():
raise models.ValidationError('Error! You cannot create recursive categories.')
Explication des différentes parties du code précédents :
_parent_store , _parent_name et parent_path
En précisant ces trois paramètres, on indique au compilateur qu’il s’agit d’une relation de hiérarchie, en précisant que le catégorie mère sera enregistrée et qui portera le nom de la catégorie mère.
parent_id=fields.Many2one('agence.categorie.vehicule',ondelete='restrict',string='Catégorie Mère',Index=True )
Le champ name portera le nom de la catégorie.
Le champ parent_id, précise une relation Plusieurs à Un ManyToOne, entre le modèle catégorie et lui-même avec l’interdiction de la suppression.
child_ids = fields.One2many( 'agence.categorie.vehicule','parent_id', ondelete='restrict',
string='Sous-Catégorie , Index=True )
Le champ child_ids, définit une relation Un à Plusieurs ou OneToMany , toujours entre le modèle et lui-même, définissant les sous catégories, de la catégorie mère (parent_id) et en interdisant la suppression.
Finalement on trouve la fonction _check_recursion(): , qui est une fonction de base Odoo et qui a pour objectif de vérifier la non existence de non récursion dans les enregistrements de l’objet en cours. Cette vérification se fait lors de sauvegarde, dans le cas d’existence d’une récursion un message d’erreur sera affiché à l’utilisateur.
2.Déclarer le nouveau fichier dans le paramètre __init__.py :
3.Ajoutez le fichier xml des vues du modèle agence.categorie.vehicule :
Pour visualiser le champ catégorie et sous catégories, ajouter dans le répertoire views le fichier agence_categorie_vehicule.xml , puis mettez dedans le code suivant qui permettra d’ajouter les vus nécessaires (sous menu, Vue Formulaire, liste et recherche) du modèle agence.categorie.vehicule:
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id='agence_categorie_vehicule_action' model='ir.actions.act_window'>
<field name="name"> Gestion des Catégories </field>
<field name="res_model">agence.categorie.vehicule</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Catégories" id="agence_categorie_veicule_menu"
parent="agence_base_menu" action="agence_categorie_vehicule_action"/>
<record id="agence_categorie_vehicule_view_form" model="ir.ui.view">
<field name="name">Agence Catégorie Vehicules Form</field>
<field name="model">agence.categorie.vehicule</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="name"/>
<field name="parent_id"/>
<field name="child_ids" widget="many2many_tags"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="agence_categorie_vehicule_tree" model="ir.ui.view">
<field name="name">Agence Catégorie Lise</field>
<field name="model">agence.categorie.vehicule</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
</tree>
</field>
</record>
<record id="agence_categorie_vehicule_search" model="ir.ui.view">
<field name="name">Agence Categorie Recherche</field>
<field name="model">agence.categorie.vehicule</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
</search>
</field>
</record>
</odoo>
4.Ajoutez le cham catégorie_id, dans le modèle agence.vehicule
category_id = fields.Many2one('agence.categorie.vehicule', string=’Catégorie’)
Ensuite, on doit déclarer ce champ dans la vue formulaire du véhicule, en ajoutant simplement la ligne de code suivante :
<field name="category_id"/>
5.Ajoutez le group et les droits d’accès au nouveau modèle agence.categorie.vehicule:
<record id="group_ag_categorie_managers" model="res.groups">
<field name="name">Agence Categorie Managers</field>
<field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>
Ensuite, dans le fichier ir.model.access.csv
acl_agence_categ_users,agence.categorie.vehicule default,model_agence_categorie_vehicule,,1,0,0,0
acl_agence_categ_admin,agence.categorie.vehicule_admin,model_agence_categorie_vehicule,group_ag_categorie_managers,1,1,1,1
6.Déclarez la nouvelle vue dans le fichier __manifest__.py :
,'views/agence_categorie_vehicule.xml'
7.Redémarrez le serveur et mettez à jour de l’application.
Vous remarquerez l’ajout de l’option de menu Catégorie, et l’ajout du champ catégorie dans le formulaire des véhicules.
Conclusion
Dans cet article nous avons découvert, comment implémenter le concept de la relation hiérarchie ou les modèles imbriqués (nested models), permettant ainsi d’étendre les autres types de relations (OneToMany, ManyToOne, ManayToMany) qui présentait des limites dans certains cas pratiques, comme la catégorisation et la composition.
Télécharger gratuitement votre guide odoo !
Découvrez comment , Odoo est une vraie opportunité pour les entreprises et les développeurs !