Décorateur de contraintes dans Odoo
Le chapitre précédent a introduit la possibilité d’ajouter de la logique métier à notre modèle. Nous pouvons maintenant lier les boutons au code métier, mais comment empêcher les utilisateurs de saisir des données incorrectes ? Par exemple, dans notre module immobilier, rien n’empêche les utilisateurs de définir un prix attendu négatif.
Odoo propose deux façons de mettre en place des invariants vérifiés automatiquement : Les contraintes Python et les contraintes SQL
SQL
Remarque
Objectif : à la fin de cette section :
Les montants doivent être (strictement) positifs
- Les types de propriété et les étiquettes doivent avoir un nom unique
Les contraintes SQL sont définies par l’attribut de modèle _sql_constraints. Cet attribut se voit attribuer une liste de triplets contenant des chaînes (name, sql_definition, message), où name est un nom de contrainte SQL valide, sql_definition est une expression de contrainte de table et message est le message d’erreur.
Python
Remarque
Objectif : à la fin de cette section, il ne sera pas possible d’accepter une offre inférieure à 90% du prix prévu.
Les contraintes SQL sont un moyen efficace de garantir la cohérence des données. Cependant, il peut être nécessaire d’effectuer des vérifications plus complexes qui requièrent du code Python. Dans ce cas, nous avons besoin d’une contrainte Python.
Une contrainte Python est définie comme une méthode décorée avec constrains() et est invoquée sur un jeu d’enregistrements. Le décorateur spécifie les champs concernés par la contrainte. La contrainte est automatiquement évaluée lorsque l’un de ces champs est modifié. La méthode est censée lever une exception si son invariant n’est pas satisfait :
from odoo.exceptions import ValidationError ... @api.constrains('date_end') def _check_date_end(self): for record in self: if record.date_end < fields.Date.today(): raise ValidationError("The end date cannot be set in the past") # all records passed the test, don't return anything
Activité : Créer une contrainte
- Ouvrez le fichier contenant le modèle
Patient
(patient.py
) dans votre éditeur de code. - Ajoutez l’import
from odoo.exceptions import ValidationError
au début du fichier. - Recherchez la classe
HospitalPatient
qui définit le modèlePatient
. - Ajoutez la méthode
_check_age_is_zero()
avec l’annotation@api.constrains('age', 'is_child')
dans la classeHospitalPatient
. - À l’intérieur de la méthode
_check_age_is_zero()
, utilisez une bouclefor rec in self
pour parcourir les enregistrements concernés. - À l’intérieur de la boucle, ajoutez une condition pour vérifier si
rec.age
est égal à 0 et querec.is_child
est activé. - Si les conditions sont remplies, utilisez
raise ValidationError("Invalid combination: Age cannot be 0 if Is Child is enabled.")
pour générer une exceptionValidationError
avec un message d’erreur approprié. - Enregistrez le fichier.
Exemple de code :
from odoo import models, fields, api
from odoo.exceptions import ValidationError
class HospitalPatient(models.Model):
..................................
@api.constrains('age', 'is_child')
def _check_age_is_zero(self):
for rec in self:
if rec.age == 0 and rec.is_child:
raise ValidationError("Invalid combination: Age cannot be 0 if Is Child is enabled.")
............................
Dans cet exercice, vous devez ajouter une contrainte qui vérifie si l’âge est égal à 0 et que is_child
est activé. Si ces conditions sont satisfaites, une exception sera générée, empêchant la validation de l’enregistrement. Assurez-vous de recharger le module Odoo après avoir effectué ces modifications pour que la contrainte prenne effet.