Odoo peut être utilisé comme un framework de développement web tout comme Django ou Flask.
Odoo se différencie de ces frameworks par le fait qu'il embarque à la base des modules orientés entreprise sous forme d'applications prêtes à l'installation.
Nous allons faire abstraction de ces modules pour nous concentrer sur Odoo en tant que framework de développement web en espérant que cela aidera à la prise en main de cette application par les développeurs.
Odoo est une application implémentée dans le langage python qui est un langage interprété (cet aspect a un impact sur le workflow de développement comme nous le verrons plus tard).
Au démarrage, Odoo a besoin d'être préconfiguré pour se connecter au gestionnaire de base de données Postgresql.
Odoo a également besoin d'être instruit des chemins (paths) où il trouvera les modules complémentaires que les développeurs ajouteront pour enrichir l'application.
Ces détails sont déjà pris en charge dans l'environnement de développement qui vous est livré à votre entrée à Elosys.
Pour favoriser un enrôlement rapide des stagiaires et des nouvelles recrues, un environnement de développement est mis à leur disposition en partie avec le dépôt https://git.elosys.net/sys/dotfiles.
Cet environnement comprend des aliases et des fonctions bash, une configuration tmux ainsi que des dispositifs docker et docker-compose.
Elosys vous fournira un dispositif minimal mais complet qui vous permettra de démarrer rapidement avec Odoo grâce à docker.
Un dossier contenant deux fichiers docker-compose.yml
et odoo.conf
vous suffira pour commencer.
$ cd service.odoo $ ll total 20K -rw-r--r-- 1 user user 683 juin 15 15:22 docker-compose.yml -rw-r--r-- 1 user user 1,2K juin 15 15:21 odoo.conf $ dcu
La commande dcu
lancera deux containers listés dans le fichier docker-compose.yml
.
Lors de ce premier lancement, vous devez attendre que le gestionnaire de base de données Postgresql initialise son cluster 1) . Cela devrait être indiqué par un message de type :
odoo_db | PostgreSQL init process complete; ready for start up. odoo_db | odoo_db | 2022-06-15 14:23:28.769 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 odoo_db | 2022-06-15 14:23:28.769 UTC [1] LOG: listening on IPv6 address "::", port 5432 odoo_db | 2022-06-15 14:23:28.852 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" odoo_db | 2022-06-15 14:23:29.005 UTC [67] LOG: database system was shut down at 2022-06-15 14:23:28 UTC odoo_db | 2022-06-15 14:23:29.059 UTC [1] LOG: database system is ready to accept connections
Une fois le cluster de base de données initialisé, arrêtez les containers en tapant Ctrl
+ c
.
Le dossier qui ne contenait jusque là que deux fichiers docker-compose.yml
et odoo.conf
contiendra trois dossiers supplémentaires :
$ ll total 20K drwx------ 19 systemd-coredump root 4,0K juin 15 15:27 data drwxr-xr-x 2 root root 4,0K juin 15 15:23 extra-addons drwxr-xr-x 2 root root 4,0K juin 15 15:23 filestore -rw-r--r-- 1 user user 683 juin 15 15:22 docker-compose.yml -rw-r--r-- 1 user user 1,2K juin 15 15:21 odoo.conf $
Vu que les dossiers spécifiques à Odoo extra-addons
et filestore
n'ont pas les bonnes autorisations, nous devrons lancer la commande ff
pour régler le problème 2)
$ ff $ ll total 20K drwx------ 19 systemd-coredump root 4,0K juin 15 15:27 data drwxr-xr-x 2 user user 4,0K juin 15 15:23 extra-addons drwxr-xr-x 2 systemd-timesync systemd-journal 4,0K juin 15 15:23 filestore -rw-r--r-- 1 user user 683 juin 15 15:22 docker-compose.yml -rw-r--r-- 1 user user 1,2K juin 15 15:21 odoo.conf $
A partir de maintenant l'environnement est prêt à recevoir vos développements.
dcu
et dcd
sont les deux commandes utilisées pour, respectivement, démarrer et arrêter les containers Odoo et Postgresql.
Nous avons auparavant vu l'usage du raccourci Ctrl
+ c
pour arrêter les deux containers (Odoo et Postgresql) en cours d'exécution sur le même terminal.
Les commandes dcd
et dcu
dépendent du fichier docker-compose.yml
. Elle doivent donc être exécutées à partir d'un dossier contenant le fichier docker-compose.yml
ou dans un sous-dossier de ce dossier.
Il est généralement pas nécessaire d'arrêter le container Postgresql. Ce qui nous importe le plush dans notre workflow de développement c'est de redémarrer l'application Odoo.
Cette tâche peut être effectuée de manière sélective en utilisant la commande :
$ docker-compose restart odoo
La commande ci-dessus ne fera qu'arrêter puis démarrer l'application Odoo. Comme les commandes dcu
et dcd
cette commande doit être exécutée dans un dossier qui contient le fichier docker-compose.yml
ou dans un sous-dossier de ce dossier.
Comme nous l'avons évoqué auparavant la nature interprétée du langage python impose un certain workflow de développement que nous allons poser ici et que nous rappelleront au cours de cette introduction :
Si vous modifiez un fichier python au cours de votre développement vous devez à minima3) redémarrer l'application Odoo pour que vos modifications soient chargées dans le nouvel interpréteur qui portera l'application Odoo.
Après avoir démarré Odoo avec dcu
, rendez-vous avec votre navigateur sur l'adresse http://127.0.0.1:8069/. Vous serez invité à créer votre première base de données.
Durant cette initialisation, observez le log de l'application sur votre terminal. Le log vous renseignera sur la procédure d'initialisation d'une installation Odoo de base. 4)
A la fin de l'initialisation de la base de données, vous serez redirigé vers la page d'accueil de l'application Odoo. 5)
Qu'est ce qu'un module Odoo ?
Un module Odoo est d'abord un paquet python.
Un paquet python est un dossier dans lequel réside un fichier nommé __init__.py
.
Un module Odoo est un paquet python dans lequel réside un fichier supplémentaire nommé __manifest__.py
.
En somme, un module Odoo est un dossier dans lequel on trouve deux fichiers __init__.py
et __manifest__.py
.
Si le fichier __init__.py
peut être vide, le fichier __manifest__.py
doit contenir un dictionnaire qui contient au moins une valeur texte pour la clé name
. 6) Comme ceci :
{ 'name': 'Mon module', }
Reste à répondre à la question : où doit-on créer ces fichiers ?
Dans le dossier extra-addons
.
Dans la suite de commandes suivante nous allons :
monmodule
dans le dossier extra-addons
__init__.py
et __manifest__.py
dans le dossier monmodule
__manifest__.py
avec le dictionnaire minimal requis.Nous allons enfin, démarrer ou redémarrer l'application Odoo.
$ ll total 20K drwx------ 19 systemd-coredump root 4,0K juin 15 15:27 data drwxr-xr-x 2 user user 4,0K juin 15 15:23 extra-addons drwxr-xr-x 2 systemd-timesync systemd-journal 4,0K juin 15 15:23 filestore -rw-r--r-- 1 user user 683 juin 15 15:22 docker-compose.yml -rw-r--r-- 1 user user 1,2K juin 15 15:21 odoo.conf $ cd extra-addons $ mkdir monmodule $ cd monmodule $ touch __init__.py $ touch __manifest__.py $ echo "{'name':'Mon Module',}" | tee __manifest__.py $ docker-compose down && docker-compose up -d
En se loggant sur l'application, la page d'accueil par défaut sur laquelle nous atterrissons est la vue consacrées aux applications disponibles.
Nous pouvons filtrer 7) pour n'afficher que les modules qui correspondent au module minimal que nous venons de créer.
Après avoir éliminé le filtre App
nous pouvons filtrer en écrivant Mon module
ou monmodule
dans la barre de recherche. Ci-dessous le résultat qui devrait s'afficher.
Nous avons vu dans ce qui a précédé :
Qu'est-ce qu'un modèle ?
Un modèle est une table dans la base de données.
Une des propriétés des frameworks de développement tels que Odoo est la possibilité de représenter et de manipuler la base de données sous une forme orientée objet. Ce dispositif implémenté dans Odoo s'appelle ORM et nous allons l'explorer dans ce qui suit pour créer et définir des tables dans la base de données Postgresql.
Nous créons notre premier modèle dans un nouveau fichier python.
$ cd ~/service.odoo/extra-addons/monmodule $ touch models.py $ editor models.py
Le fichier models.py
contiendra le strict minimum pour créer un model dans la base de données.
from odoo import models class Professeur(models.Model): _name = 'elo.prof'
Pour créer un modèle nous utilisons une classe qui hérite de la classe models.Model
.
Le nom de la table dans la base de données (model name) est défini par la valeur de l'attribut spécial _name
.
Pour que le nouveau fichier models.py
soit chargé et évalué par l'interpréteur Python, nous devons le répertorier dans le fichier __init__.py
du module, comme suit :
$ cd ~/service.odoo/extra-addons/monmodule $ echo "from . import models" | tee -a __init__.py $ cat __init__.py from . import models $
Vu que nous avons édité des fichiers python dans notre module (__init__.py et ajouté un nouveau fichier models.py), nous devons redémarrer Odoo pour que ces modifications soient chargées par l'interpréteur qui embarque l'application Odoo.
Après le redémarrage d'Odoo, nous nous rendons à la vue App
et nous filtrons sur notre application monmodule
comme indiqué ici monmodule.png.
Il ne reste qu'à appuyer sur le boutton Install
.
Voici ce que nous pouvons lire dans le log de l'application après avoir appuyé sur le bouton.
01 odoo | ..... 1 INFO base odoo.addons.base.models.ir_module: ALLOW access to module.button_immediate_install on ['monmodule'] to user admin #2 via 172.17.0.1 02 odoo | ..... 1 INFO base odoo.addons.base.models.ir_module: User #2 triggered module installation 03 odoo | ..... 1 INFO base odoo.addons.base.models.ir_module: ALLOW access to module.button_install on ['monmodule'] to user admin #2 via 172.17.0.1 04 odoo | ..... 1 INFO base odoo.modules.loading: loading 1 modules... 05 odoo | ..... 1 INFO base odoo.modules.loading: 1 modules loaded in 0.03s, 0 queries (+0 extra) 06 odoo | ..... 1 INFO base odoo.modules.loading: updating modules list 07 odoo | ..... 1 INFO base odoo.addons.base.models.ir_module: ALLOW access to module.update_list on [] to user __system__ #1 via 172.17.0.1 08 odoo | ..... 1 INFO ? werkzeug: 172.17.0.1 - - [05/Jul/2022 11:18:12] "GET /web/static/src/img/spin.png HTTP/1.1" 200 - - - - 09 odoo | ..... 1 INFO base odoo.modules.loading: loading 8 modules... 10 odoo | ..... 1 INFO base odoo.modules.loading: 8 modules loaded in 0.03s, 0 queries (+0 extra) 11 odoo | ..... 1 INFO base odoo.modules.loading: loading 9 modules... 12 odoo | ..... 1 INFO base odoo.modules.loading: Loading module monmodule (2/9) 13 odoo | ..... 1 WARNING base odoo.models: The model elo.prof has no _description 14 odoo | ..... 1 INFO base odoo.modules.registry: module monmodule: creating or updating database tables 15 odoo | ..... 1 INFO base odoo.modules.loading: Module monmodule loaded in 1.43s, 35 queries 16 odoo | ..... 1 INFO base odoo.modules.loading: 9 modules loaded in 1.43s, 35 queries (+0 extra) 17 odoo | ..... 1 WARNING base odoo.modules.loading: The model elo.prof has no access rules, consider adding one. E.g. access_elo_prof,access_elo_prof,model_elo_prof,base.group_user,1,0,0,0
Install
a bien été enregistrée et appelle la méthode correspondante module.button_immediate_install
.Loading module monmodule
_description
pour le model elo.prof
que nous nous apprêtons à créer grâce aux instructions du fichiers models.py
de notre module.elo.prof
que nous venons de créer. 8)Comment vérifier que notre modèle a bien été crée par Odoo dans la base de données ?
Même si cette page de référence du site Odoo présente plusieurs façons d'activer le mode développeur dans l'interface web de Odoo, nous vous recommandons d'installer l'extension Odoo Debug disponible pour Firefox et pour Chrome
En activant le mode développeur, vous avez accès à des menus et des fonctionnalités supplémentaires qui vous aideront à mieux introspecter votre installation Odoo.
Ci-dessous, vous verrez des menus supplémentaire sur la vue App
à l'activation du mode debug.
Une étude extensive de l'usage du debug mode est abordée sur un autre support. TODO
Dans le menu Settings
appuyer sur Technical
et scroller jusqu'à la section Database Structure
et sélectionner Models
.
Les modèles installés dans votre base de données sont eux-mêmes répertoriés dans un modèle spécifique du nom de ir.model
.
Dans cette vue sur les enregistrements du model ir.model
, nous avons donc l'intégralité des tables existantes dans notre installation Odoo.
Nous pouvons filtrer pour chercher la table que nous avons créée dans notre fichier models.py
en inscrivant elo
dans la zone de recherche.
Notre table elo.prof
devrait apparaître comme dans la capture suivante.
En sélectionnant cet enregistrement, nous en aurons donc une vue détaillée que nous appelons vue formulaire (ou form view en anglais).
Dans cette vue nous pouvons déjà voir les champs qui ont été automatiquement créés par Odoo à la création du model. Les champs correspondent aux colonnes d'une table de base de données.
Ces champs automatiques sont nécessaire au fonctionnement interne d'Odoo.
Nous verrons plus tard comment ajouter nos propres champs à nos modèles.
Nous allons ici apprendre comment interagir en ligne de commande avec le gestionnaire de base de données qui s'exécute à l'intérieur de docker.
Pour exécuter le client psql, nous lanceront la commande suivante dans le terminal. (Il faut que le gestionnaire de base de données soit en cours d'exécution)
$ docker exec -it odoo_db psql -U postgres psql (10.0) Type "help" for help. postgres=#
La commande précédente nous connecte avec l'utilisateur postgres sur la base de données de maintenance du même nom.
Nous allons dans ce qui suit
postgres=# \c base You are now connected to database "base" as user "postgres". base=# \d elo_prof Table "public.elo_prof" Column | Type | Collation | Nullable | Default -------------+-----------------------------+-----------+----------+-------------------------------------- id | integer | | not null | nextval('elo_prof_id_seq'::regclass) create_uid | integer | | | create_date | timestamp without time zone | | | write_uid | integer | | | write_date | timestamp without time zone | | | Indexes: "elo_prof_pkey" PRIMARY KEY, btree (id) Foreign-key constraints: "elo_prof_create_uid_fkey" FOREIGN KEY (create_uid) REFERENCES res_users(id) ON DELETE SET NULL "elo_prof_write_uid_fkey" FOREIGN KEY (write_uid) REFERENCES res_users(id) ON DELETE SET NULL base=#
Relevons la différence qu'il y a entre la représentation du modèle dans Odoo et dans le gestionnaire de base de données.
elo.prof
dans Odoo devient elo_prof
dans le gestionnaire de base de données.
Notre modèle ne contient jusqu'à cette étape que les champs (colonnes) créés automatiquement par Odoo pour son fonctionnement interne.
En général, nous aurons besoin de définir des champs supplémentaires pour porter l'identité et le fonctionnement de notre modèle.
Pour cela, nous allons éditer notre modèle dans le fichier models.py
pour lui ajouter de nouveaux champs.
from odoo import models, fields class Professeur(models.Model): _name = 'elo.prof' _description = 'Professor Card' name = fields.Char(string="Professor Name") bio = fields.Text(string="Short Bio")
Les champs des modèles sont définis comme des attributs. Ici, nous en créons deux, les champs name
et bio
qui sont respectivement de type Char
et Text
9).
Les champs sont des instances de classes du module fields
que nous avons importé à la première ligne en plus du module models
.
Nous avons ajouté l'attribut spécial _description
pour faire taire le WARNING vu lors de l'installation du module.
Nous rappelons encore une fois que modifier un fichier python nécessite le redémarrage de l'application Odoo. Ici, vu que nous avons modifié la définition d'un model, en ajoutant ou modifiant ses champs, nous devons en plus upgrader le module pour que ces modifications soient répercutées dans la base de données.
Pour mettre à jour notre module, nous revenons à la vue Apps
et nous sélectionnons Upgrade
après avoir appuyé sur les trois points d'extension verticaux dans le coin haut-droit du post-it kanban réservé à notre module.
Et voici donc ce qui apparaîtera dans votre terminal après avoir appuyé sur le bouton.
odoo | .... INFO base odoo.addons.base.models.ir_module: ALLOW access to module.button_immediate_upgrade on ['monmodule'] to user admin #2 via 172.17.0.1 odoo | .... INFO base odoo.addons.base.models.ir_module: ALLOW access to module.button_upgrade on ['monmodule'] to user admin #2 via 172.17.0.1 .... odoo | .... INFO base odoo.modules.loading: loading 1 modules... .... odoo | .... INFO base odoo.modules.loading: Loading module monmodule (2/9) odoo | .... INFO base odoo.modules.registry: module monmodule: creating or updating database tables .... odoo | .... WARNING base odoo.modules.loading: The model elo.prof has no access rules, consider adding one. E.g. access_elo_prof,access_elo_prof,model_elo_prof,base.group_user,1,0,0,0 odoo | .... INFO base odoo.modules.registry: verifying fields for every extended model odoo | .... INFO base odoo.modules.loading: Modules loaded.
Le WARNING sur l'absence de description du modèle a disparu mais le WARNING sur l'absence de règles d'accès (access rules) est toujours présent.
Nous verrons comment le traiter dans la partie suivante.
Mais avant cela nous allons examiner notre modèle dans Odoo et dans Postgresql pour voir nos modifications.
$ docker exec odoo_db psql -U postgres -d base -c '\d+ elo_prof' Table "public.elo_prof" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description -------------+-----------------------------+-----------+----------+--------------------------------------+----------+--------------+----------------- id | integer | | not null | nextval('elo_prof_id_seq'::regclass) | plain | | create_uid | integer | | | | plain | | Created by create_date | timestamp without time zone | | | | plain | | Created on write_uid | integer | | | | plain | | Last Updated by write_date | timestamp without time zone | | | | plain | | Last Updated on name | character varying | | | | extended | | Professor Name bio | text | | | | extended | | Short Bio Indexes: "elo_prof_pkey" PRIMARY KEY, btree (id) Foreign-key constraints: "elo_prof_create_uid_fkey" FOREIGN KEY (create_uid) REFERENCES res_users(id) ON DELETE SET NULL "elo_prof_write_uid_fkey" FOREIGN KEY (write_uid) REFERENCES res_users(id) ON DELETE SET NULL $
Sur les deux représentations du modèle elo.prof
nous pouvons voir que les champs name
et bio
ont été correctement ajoutés.
Les droits d'accès sont le mécanisme utilisé pour définir les autorisations sur les modèles.
Grâce aux droits d'accès nous pouvons dire si tel groupe d'utilisateurs a le droit de lecture, de modification, de création ou d'effacement sur les enregistrements d'un modèle.
C'est un des nombreux mécanismes utilisables dans Odoo pour gérer les droits d'accès sur les modèles.
Pour implémenter les droits d'accès nous devons d'abord les déclarer dans le manifeste de notre module.
Nous allons donc éditer le fichier __manifest__.py
ainsi :
{ 'name':'Mon Module', 'data': [ 'ir.model.access.csv', ], }
Nous avons ajouté au manifest une nouvelle clé data
dont la valeur est une liste dont chaque élément est le nom d'un fichier qui est supposé contenir de la data.
Le nom de ce fichier correspond à un des modèles préchargés dans Odoo et dont Odoo se sert pour son fonctionnement interne.
Le modèle ir.model.access
est le modèle qu'utilise Odoo pour conserver les droits d'accès sur les autres modèles.
Nous allons donc créer le ir.model.access.csv
$ cd ~/service.odoo/extra-addons/monmodule $ touch ir.model.access.csv
Et nous allons le remplir avec le contenu suivant :
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_elo_prof,access_elo_prof,model_elo_prof,base.group_user,1,1,1,1
id | name | model_id:id | group_id:id | perm_read | perm_write | perm_create | perm_unlink |
access_elo_prof | access_elo_prof | model_elo_prof | base.group_user | 1 | 1 | 1 | 1 |
Apps
qui liste les modules disponibles à l'installation