Outils pour utilisateurs

Outils du site


nsi:projets:sql

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
nsi:projets:sql [2021/10/25 16:49] goupillwikinsi:projets:sql [2022/10/18 09:57] (Version actuelle) goupillwiki
Ligne 60: Ligne 60:
 <WRAP tip>Vous êtes libre d'utiliser un logiciel comme SQLiteBrowser pour créer la vase vide.</WRAP> <WRAP tip>Vous êtes libre d'utiliser un logiciel comme SQLiteBrowser pour créer la vase vide.</WRAP>
  
-Supposons que nous avons créé la base {{ :nsi:terminales:films.db |}}. Elle est vide à la première utilisation mais au gré des utilisations, elle va se remplir.+Supposons que nous avons créé la base {{ :nsi:terminales:database:films.db |}}. Elle est vide à la première utilisation mais au gré des utilisations, elle va se remplir.
  
 Votre application, en Python, propose une interface utilisateur permettant la manipulation de la BDD. Votre application, en Python, propose une interface utilisateur permettant la manipulation de la BDD.
Ligne 162: Ligne 162:
  
 Comme déjà dit c'est un travail répétitif et il faut bien vous organiser pour ne pas perdre du temps à réécrire 2x le même code. Comme déjà dit c'est un travail répétitif et il faut bien vous organiser pour ne pas perdre du temps à réécrire 2x le même code.
 +
 +===== Aide pour organiser votre code =====
 +
 +Vous avez intérêt à bien séparer la partie SQL de l'interface graphique.
 +
 +==== Exemple de ce qu'il ne faut pas faire ====
 +
 +Supposons que je travaille sur la base des films et que je veux gérer l'ajout d'un artiste. Je peux être tenté d'écrire :
 +
 +<code python>
 +import sqlite3
 +
 +# variables globales
 +c = sqlite3.connect("films.db")
 +c.execute("PRAGMA foreign_keys = 1")
 +
 +def ajout_artiste():
 +    prenom = input("Donnez un prénom :")
 +    nom = input("Donnez un nom :")
 +    naissance = input("Donnez une date de naissance :")
 +    bio = input("Donnez une biographie :")
 +    cursor = c.cursor()
 +    data = (prenom, nom, biographie, naissance)
 +    cursor.execute("INSERT INTO ARTISTE(prénom, nom, biographie, naissance) VALUES(?, ?, ?, ?);", data)
 +</code>
 +
 +Ce code mélange l'interface graphique avec le code SQL. Ce n'est pas une bonne chose.
 +
 +==== Ce qu'il vaut mieux faire ====
 +
 +Il est beaucoup mieux de placer le SQL dans un module à part. On pourrait faire ceci :
 +
 +<code python>
 +# fichier sql.py, compris par Python comme le module sql
 +import sqlite3
 +
 +# variables globales
 +c = sqlite3.connect("films.db")
 +c.execute("PRAGMA foreign_keys = 1")
 +
 +def ajout_artiste(prenom, nom, naissance, bio):
 +    cursor = c.cursor()
 +    data = (prenom, nom, biographie, naissance)
 +    cursor.execute("INSERT INTO ARTISTE(prénom, nom, biographie, naissance) VALUES(?, ?, ?, ?);", data)
 +</code>
 +
 +<code python>
 +# module principal
 +import sql
 +
 +def ajout_artiste():
 +    prenom = input("Donnez un prénom :")
 +    nom = input("Donnez un nom :")
 +    naissance = input("Donnez une date de naissance :")
 +    bio = input("Donnez une biographie :")
 +    sql.ajout_artiste(prenom, nom, naissance, bio)
 +</code> 
 +
 +Remarquez qu'on utilise la notation avec le point pour signifier que ''ajout_artiste'' est une fonction de module ''sql''. C'est bienvenue car cela nous permet de mieux trier notre code et de bien voir où sont les choses.
 +
 +Vous avez intérêt, dès que votre application prend du volume, à en distribuer les parties en autant de modules que possible afin de maintenir l'ensemble mieux organiser.
 +
 +==== Encore mieux avec une classe ====
 +
 +C'est encore mieux si on emballe les fonctions sql dans une classe faite exprès.
 +
 +<code python>
 +# fichier sql.py, compris par Python comme le module sql
 +import sqlite3
 +
 +class SQL:
 +    def __init__(self):
 +        self.c = sqlite3.connect("films.db")
 +        self.c.execute("PRAGMA foreign_keys = 1")
 +
 +    def ajout_artiste(self, prenom, nom, naissance, bio):
 +        cursor = c.cursor()
 +        data = (prenom, nom, biographie, naissance)
 +        cursor.execute("INSERT INTO ARTISTE(prénom, nom, biographie, naissance) VALUES(?, ?, ?, ?);", data)
 +</code>
 +
 +<code python>
 +# module principal
 +from sql import SQL
 +
 +# au début on pense à créer :
 +db = SQL() # crée l'objet et exécute le __init__
 +
 +def ajout_artiste():
 +    prenom = input("Donnez un prénom :")
 +    nom = input("Donnez un nom :")
 +    naissance = input("Donnez une date de naissance :")
 +    bio = input("Donnez une biographie :")
 +    db.ajout_artiste(prenom, nom, naissance, bio)
 +</code>
 +
 +==== Enrichir la classe ====
 +
 +La classe contient toutes les requêtes utiles. Supposez que vous ayez besoin d'une requête pour obtenir uniquement une liste de noms et prénoms d'artistes, alors vous écrivez une fonction qui fait cela. Si vous avez besoin d'une requête listant les films pour un certain //idReal//, vous faites une fonction pour...
 +
 +À la fin, il n'y a pas une seule requête SQL dans le fichier principal.
 +
 +Exemple de classe :
 +
 +<code python>
 +# module sql
 +
 +import sqlite3
 +
 +class SQL:
 +    def __init__(self):
 +        self.c = sqlite3.connect("films.db")
 +        self.c.execute("PRAGMA foreign_keys = 1")
 +        self.__is_closed = False
 +
 +    def __init_db(self):
 +        # crée les tables en cas de première utilisation
 +        # suffit d'utiliser le mot clé IF NOT EXISTS
 +        # de sorte que si elles existent déjà, rien n'est fait
 +        cursor = self.c
 +        cursor.execute("CREATE TABLE IF NOT EXISTS ARTISTE (idArtiste INTEGER PRIMARY KEY, nom VARCHAR(20), prénom VARCHAR(20), biographie TEXT, naissance DATE);")
 +        
 +        # on peut ainsi créer les autres
 +        
 +    def close(self):
 +        # À appeler à la fermeture pour appliquer les modifs et libérer le fichier
 +        self.c.commit()
 +        self.c.close()
 +        self.__is_closed = True
 +
 +    def ajout_artiste(self, prenom:str, nom:str, naissance:str, bio:str):
 +        assert not self.__is_closed, "La base est fermée..."
 +        cursor = c.cursor()
 +        data = (prenom, nom, biographie, naissance)
 +        cursor.execute("INSERT INTO ARTISTE(prénom, nom, biographie, naissance) VALUES(?, ?, ?, ?);", data)
 +
 +    def get_films_from_real(self, id_real:int) -> list:
 +        # liste des films pour un réal donné
 +        assert not self.__is_closed, "La base est fermée..."
 +        cursor = c.cursor()
 +        cursor.execute("SELECT * FROM FILMS WHERE idReal = ?", (id_real,))
 +        return cursor.fetchall()
 +</code>
 +
 +==== Pousser plus loin ====
 +
 +Dès que l'application prend du volume, on se retrouve avec un mélange compliqué de code, d'input, de chaînes de textes... Comme on a séparé les requêtes SQL du reste, on va avoir intérêt à mettre tout ce qui est texte de côté.
 +
 +C'est plus compliqué alors pour cela j'ouvre une [[.:sql_controleur|nouvelle page]].
 +
 +
nsi/projets/sql.1635173347.txt.gz · Dernière modification : de goupillwiki