{{tag>dev python flask orm db sqlalchemy}} ====== Flask-SQLAlchemy : relation one-to-many ====== Quelques notes à propos de l'implémentation d'une relation un à plusieurs (one to many) avec l'extension Flask-SQLAlchemy. Pour illustrer le concept on prend un exemple rudimentaire : {{ex_mcd_shop_products.png}} MCD via diagramme UML * Un magasin (Shop) vend un ou plusieurs produits (Product); * Un produit est vendu par un seul magasin. ===== Implémentation ===== Ci-dessous l'application Flask minimaliste implémentant les deux classes du modèle et la relation one-to-many. from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class Shop(db.Model): __tablename__ = 'shops' id = db.Column(db.Integer, primary_key=True, index=True) name = db.Column(db.String(80), unique=True, index=True) products = db.relationship("Product", back_populates="shop", lazy='dynamic') def add_product(self, product): if self.id is None : # Le magasin doit exister en base avant d'ajouter un produit db.session.add(self) db.session.commit() product.shop_id = self.id db.session.add(product) db.session.commit() class Product(db.Model): __tablename__ = 'products' id = db.Column(db.Integer, primary_key=True, index=True) name = db.Column(db.String(80), unique=True, index=True) price = db.Column(db.Float(precision=2)) shop_id = db.Column(db.Integer, db.ForeignKey('shops.id'), unique=False, nullable=False) shop = db.relationship("Shop", back_populates="products") # Création de l'application # On utilise la variable __name__ pour définir le nom du module courant # comme root applicatif pour notre application flask app = Flask(__name__) # Le chemin vers la base SQLite est relatif au dossier de l'application flask app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///database.db" # Initialiser l'application Flask par l'intermédiaire de l'extension db.init_app(app) :TODO_DOCUPDATE: * Lignes 7 et 27 : les classes doivent hériter de db.Model pour que les objets puissent être enrgistrés dans la bbase de données; * Pour chaque attribut on définit sous quelle forme il sera stocké dans la base; La relation one-to-many ==== L'option lazy="dynamic" de la méthode db.relationship ==== A la ligne 12, on peut voir que l'option **''lazy="dynamic"''** est utilisée pour définir la relation. Lorsque cette option est utilisée, l'attribut ''Shop.products'' **ne retourne plus directement la liste complète** de tous les produits désignés par la relation. Au lieu de cela, ''Shop.products'' retourne un objet de type requête : cela permet notamment de **définir des critères de sélection**. ===== Test et utilisation ===== Pour tester l'implémentation, on peut lancer l'application flask en mode interactif : flask shell >>> # Afficher les références >>> # Création de la base >>> # Instanciation d'un magasin et de quelques produits >>> # Ne récupérer que les produits dont le prix est supérieur à 30€ >>> rqt.filter(Product.price>30.0).all() >>> # Utilisation de la fonction LIKE >>> rqt.filter(Product.name.like('%Ri%')).all() ===== Références ===== * [[https://pratapsharma.io/flask-sql-alchemy-one-to-many-relationship/|Mise en oeuvre d'une relation one-to-many avec Flask-SQLAlchemy]]