Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
python:flask:flask_sqlalchemy [2022/11/14 14:45] marclebrun |
python:flask:flask_sqlalchemy [2023/12/08 08:23] (Version actuelle) marclebrun |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Flask-SQLAlchemy ====== | ====== Flask-SQLAlchemy ====== | ||
- | * Doc de **SQLAlchemy 1.4** : [[https://docs.sqlalchemy.org/en/14/contents.html]] | + | * Doc de **SQLAlchemy 2.0** : [[https://docs.sqlalchemy.org/en/20/]] |
* Doc de **Flask-SQLAlchemy** : [[https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/]] | * Doc de **Flask-SQLAlchemy** : [[https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/]] | ||
* [[python:flask:flask_sqlalchemy:installation_configuration]] | * [[python:flask:flask_sqlalchemy:installation_configuration]] | ||
* [[python:flask:flask_sqlalchemy:connexion]] | * [[python:flask:flask_sqlalchemy:connexion]] | ||
+ | * [[python:flask:flask_sqlalchemy:modeles]] | ||
* [[python:flask:flask_sqlalchemy:requetes_select]] | * [[python:flask:flask_sqlalchemy:requetes_select]] | ||
+ | * [[python:flask:flask_sqlalchemy:requetes_insert]] | ||
+ | * [[python:flask:flask_sqlalchemy:requetes_update]] | ||
+ | * [[python:flask:flask_sqlalchemy:requetes_delete]] | ||
+ | * [[python:flask:flask_sqlalchemy:flask_shell]] | ||
- | ===== Connexion ===== | ||
- | <code python app/__init__.py> | ||
- | # Import des modules de Flask et de ses extensions | ||
- | from flask import Flask | ||
- | from flask_sqlalchemy import SQLAlchemy | ||
- | |||
- | # Création de l'application et import de la configuration | ||
- | app = Flask(__name__) | ||
- | app.config.from_object('config') | ||
- | |||
- | # Création de la DB | ||
- | db = SQLAlchemy(app) | ||
- | |||
- | # Import et enregistrement des composants de l'application | ||
- | from app.controllers.admin import admin | ||
- | from app.controllers.auth import auth | ||
- | from app.controllers.main import main | ||
- | app.register_blueprint(admin) | ||
- | app.register_blueprint(auth) | ||
- | app.register_blueprint(main) | ||
- | |||
- | # Import de modèles (si on en utilise dans le code qui suit) | ||
- | from app.models.user import User | ||
- | from app.models.role import Role | ||
- | |||
- | # ... | ||
- | </code> | ||
- | |||
- | ===== Modèles ===== | ||
- | |||
- | Un modèle est une classe Python qui représente les enregistrements d'une table. | ||
- | |||
- | <code python app/models/role.py> | ||
- | from app import db | ||
- | |||
- | class Role(db.Model): | ||
- | __tablename__ = 'roles' | ||
- | id = db.Column(db.Integer, primary_key=True) | ||
- | name = db.Column(db.String(64), unique=True) | ||
- | | ||
- | def __repr__(self): | ||
- | return '<Role %r>' % self.name | ||
- | </code> | ||
- | |||
- | <code python app/models/user.py> | ||
- | from app import db | ||
- | |||
- | class User(db.Model): | ||
- | __tablename__ = 'users' | ||
- | id = db.Column(db.Integer, primary_key=True) | ||
- | username = db.Column(db.String(64), unique=True, index=True) | ||
- | email = db.Column(db.String(200), unique=True) | ||
- | | ||
- | def __repr__(self): | ||
- | return '<User %r>' % self.username | ||
- | | ||
- | def hello(self): | ||
- | print("Hello, my name is %s." % self.name) | ||
- | </code> | ||
- | |||
- | ==== Clé primaire ==== | ||
- | |||
- | Une **clé primaire** est obligatoire pour chaque table, elle est généralement | ||
- | appelée **id**. | ||
- | |||
- | ==== Types de colonnes ==== | ||
- | |||
- | ^Nom ^ Type Python ^ | ||
- | ^Integer |int |Regular integer, typically 32 bits | | ||
- | ^SmallInteger|int |Short-range integer, typically 16 bits | | ||
- | ^BigInteger |int or long |Unlimited precision integer | | ||
- | ^Float |float |Floating-point number | | ||
- | ^Numeric |decimal.Decimal |Fixed-point number | | ||
- | ^String |str |Variable-length string | | ||
- | ^Text |str |Variable-length string, optimized for large or unbounded length | | ||
- | ^Unicode |unicode |Variable-length Unicode string | | ||
- | ^UnicodeText |unicode |Variable-length Unicode string, optimized for large or unbounded length | | ||
- | ^Boolean |bool |Boolean value | | ||
- | ^Date |datetime.date |Date value | | ||
- | ^Time |datetime.time |Time value | | ||
- | ^DateTime |datetime.datetime |Date and time value | | ||
- | ^Interval |datetime.timedelta |Time interval | | ||
- | ^Enum |str |List of string values | | ||
- | ^PickleType |Any Python object |Automatic Pickle serialization | | ||
- | ^LargeBinary |str |Binary blob | | ||
- | |||
- | ==== Options des colonnes ==== | ||
- | |||
- | ^primary_key |If set to True, the column is the table’s primary key. | | ||
- | ^unique |If set to True, do not allow duplicate values for this column. | | ||
- | ^index |If set to True, create an index for this column, so that queries are more efficient. | | ||
- | ^nullable |If set to True, allow empty values for this column. If set to False, the column will not allow null values. | | ||
- | ^default |Define a default value for the column. | | ||
- | |||
- | ===== Relations ===== | ||
- | |||
- | ==== One-to-many ==== | ||
- | |||
- | **One** Role <=> **Many** Users : | ||
- | |||
- | <code python> | ||
- | class Role(db.Model): | ||
- | __tablename__ = 'roles' | ||
- | id = db.Column(db.Integer, primary_key=True) | ||
- | name = db.Column(db.String(200)) | ||
- | # ... | ||
- | users = db.relationship('User', backref='role') | ||
- | | ||
- | class User(db.Model): | ||
- | __tablename__ = 'users' | ||
- | id = db.Column(db.Integer, primary_key=True) | ||
- | name = db.Column(db.String(200)) | ||
- | # ... | ||
- | role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) | ||
- | </code> | ||
- | |||
- | * Dans le modèle **User** : ''roles.id'' identifie la colonne ''id'' de la table ''roles'' comme | ||
- | "clé étrangère" dans la relation. | ||
- | * Dans le modèle **Role** : ''backref'' ajoute un attribut ''role'' au modèle **User**. | ||
- | |||
- | <code python> | ||
- | >>> r = Role(nom='Manager') | ||
- | >>> u = User(nom='Marc', role=r) | ||
- | |||
- | >>> u.nom | ||
- | 'Marc' | ||
- | |||
- | >>> u.role.nom | ||
- | 'Manager' | ||
- | </code> | ||
- | |||
- | |||
- | ==== Many-to-many ==== | ||
- | |||
- | Voir [[https://stackoverflow.com/questions/19598578/how-do-primaryjoin-and-secondaryjoin-work-for-many-to-many-relationship-in-s]] | ||
- | |||
- | |||
- | ===== Manipuler les modèles depuis le Shell ===== | ||
- | |||
- | **Flask shell** permet d'interagir avec l'application, et notamment | ||
- | de manipuler les modèles, modifier des données, etc. | ||
- | |||
- | <code bash> | ||
- | $ flask shell | ||
- | >>> from app import db | ||
- | >>> from app.models import User | ||
- | |||
- | # création d'une instance | ||
- | >>> u = User() | ||
- | >>> u.name = 'Marc' | ||
- | >>> u.email = 'marc@email.com' | ||
- | |||
- | # ajout dans la db | ||
- | >>> db.session.add(u) | ||
- | >>> db.session.commit() | ||
- | |||
- | # modification | ||
- | >>> u.name = 'Marcounet' | ||
- | >>> db.session.commit() | ||
- | </code> | ||
- | |||
- | ===== Création/mise à jour de la DB ===== | ||
- | |||
- | Après avoir créé/modifié les modèles, il faut appliquer les changements | ||
- | dans la base de données (ajout de tables, création de champs, etc.) | ||
- | |||
- | Ne rien faire manuellement, mais utiliser les | ||
- | [[python:flask:flask_migrate|Migrations]]. | ||
- | |||
- | ===== Requêtes ===== | ||
- | |||
- | Source: [[https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/queries/]] | ||
- | |||
- | **SELECT** selon un ID : | ||
- | |||
- | <code python> | ||
- | user = User.query.get(5) | ||
- | </code> | ||
- | |||
- | **SELECT** selon le contenu d'un champ : | ||
- | |||
- | <code python> | ||
- | user = User.query.filter_by(name = 'Marc').first() | ||
- | user = User.query.filter_by(name = 'Marc').one() | ||
- | </code> | ||
- | |||
- | **INSERT** | ||
- | |||
- | <code python> | ||
- | user = User(name="Marc", ...) | ||
- | db.session.add(user) | ||
- | db.session.commit() | ||
- | </code> | ||
- | |||
- | **DELETE** selon un ID : | ||
- | |||
- | <code python> | ||
- | user = User.query.get(5) | ||
- | db.session.delete(user) | ||
- | db.session.commit() | ||
- | </code> | ||
- | |||
- | **DELETE** plusieurs ligne selon un critère : | ||
- | |||
- | <code python> | ||
- | users = User.query.filter_by(active = True).all() | ||
- | for user in users: | ||
- | db.session.delete(user) | ||
- | db.session.commit() | ||
- | </code> | ||