{{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]]