SPA – les bases de données
En 2022, on estime que 41 186 animaux ont été adoptés à la SPA et 44 199 animaux ont été recueillis par celle-ci. Afin de pouvoir répertorier les animaux présents à la SPA, une table de données est l’outil indispensable.
I – Présentation du projet
Pour commencer, la réalisation de la base de données se porte sur la simulation d’une SPA. Celle-ci se compose d’une page d’Acceuil comportant le menu en haut de la page.
Puis d’une page Ajouter où l’on rentre les informations sur un nouvel animal.
Par la suite, d’une page Modifier permettant de modifier les informations sur un animal déjà enregistré sur la base de données en rentrant son id et en choisissant la donnée à modifier. De plus, lorsque vous choisissez de supprimer un animal, il vous suffit de rentrer son id et de cliquer sur Supprimer l’animal ayant cet id.
Et enfin, la page Parcourir où l’on choisit par quel type de donnée nous souhaitons faire la recherche (id, espèce, race, nom, date et lieu) et où l’on écrit la valeur recherchée ou si c’est une date, si elle est égale, plus grande, plus petites, etc.
Pour chaque page, il est possible de supprimer toute la table, c’est-à-dire supprimer tout le tableau crée. Lorsque vous ajoutez et modifiez, le résultat de Parcourir se trouve sur la fenêtre blanche en dessous de Rechercher.
II – Mise en place du projet
Dans un premier temps, il a été primordial d’importer les librairies présentes pour la création de la base de données.
from tkinter import * from tkinter import ttk from tkinter.messagebox import showinfo import sqlite3
La première ligne de code permet d’utiliser le nom des classes et fonctions définies sur tkinter. La seconde permet de créer des widgets. La troisième, showinfo permet de fournir des instructions à l’utilisateur. Enfin, d’importer le module SQLite3 permet d’interagir avec la base de données en .db .
Après avoir importé les modules dont on a besoin, il faut établir une connexion avec la base de données « base_SPA.db » et créer un curseur pour exécuter les commandes SQL .
connection = sqlite3.connect('base_SPA.db') curseur = connection.cursor()
Ensuite, il faut créer les différentes fenêtres telles que accueil, ajouter, modifier, parcourir qui sont présents tout le long et dès le début à la page Accueil avec le bouton pour vider la table, c'est-à-dire effacer les données de la table.
from tkinter import * from tkinter import ttk from tkinter.messagebox import showinfo import sqlite3 #génération du lien de la base de donnée connection = sqlite3.connect('base_SPA.db') curseur = connection.cursor() #génération de la base de donnée si elle n'existe pas curseur.execute("CREATE TABLE IF NOT EXISTS ANNIMAL(id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, nom TEXT, espèce TEXT, race TEXT, age INT, trouvé_où TEXT)") connection.commit() curseur.close() connection.close() # création de toutes les fenêtres def afficher_nouvelle_fenetre(message): fenetre.withdraw() # Masque la fenêtre actuelle nouvelle_fenetre = Toplevel(fenetre) nouvelle_fenetre.title("Nouvelle Fenêtre") nouvelle_fenetre.geometry("720x555") Label(nouvelle_fenetre, text=message).pack(padx=20, pady=20) def affiche_acceuil(): cadre_pile.append(cadre_acceuil) # création de la page d'accueil afficher_cadre(cadre_acceuil) def affiche_ajoute(): cadre_pile.append(cadre_ajoute) # création de la page ajoute afficher_cadre(cadre_ajoute) def affiche_modifier(): cadre_pile.append(cadre_modifier) # création de la page modifier afficher_cadre(cadre_modifier) def affiche_parcourir(): cadre_pile.append(cadre_parcourir) # création de la page parcourir afficher_cadre(cadre_parcourir) def afficher_cadre(cadre): for c in [cadre_acceuil, cadre_ajoute, cadre_modifier, cadre_parcourir]: c.pack_forget() cadre.pack() #génération de la fenêtre fenetre = Tk() fenetre.title("SPA - les bases de données") fenetre.geometry("720x555") fenetre.config(bg="#C2C2C2") fenetre.iconbitmap("logo.ico") #fonction pour vider la table def vider_table(): connection = sqlite3.connect('base_SPA.db') curseur = connection.cursor() curseur.execute("DROP TABLE ANNIMAL") curseur.execute("CREATE TABLE ANNIMAL(id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, nom TEXT, espèce TEXT, race TEXT, age INT, trouvé_où TEXT)") connection.commit() curseur.close() connection.close() bouton_vider_table = Button(fenetre, text="vider la table", font=("Consolas",15), bg="white", fg="black",command = vider_table) bouton_vider_table.place(x=530,y=480) # Cadres pour différentes pages cadre_acceuil = Frame(fenetre, bg="#C2C2C2") cadre_ajoute = Frame(fenetre, bg="#C2C2C2") cadre_modifier = Frame(fenetre, bg="#C2C2C2") cadre_parcourir = Frame(fenetre, bg="#C2C2C2") cadre_acceuil.pack() # Création du menu menubar = Menu(fenetre) # Ajout des commandes directement au menu principal menubar.add_command(label="Acceuil", command=affiche_acceuil) menubar.add_command(label="Ajouter", command=affiche_ajoute) menubar.add_command(label="Modifier", command=affiche_modifier) menubar.add_command(label="Parcourir", command=affiche_parcourir) # Configuration de la fenêtre avec la barre de menus fenetre.config(menu=menubar) # Initialisation de la pile des cadres cadre_pile = [cadre_acceuil] fenetre.mainloop()
Les fonctions permettent de gérer la navigation entre les différentes pages en fonction des actions de l’utilisateur. De plus, elles permettent de masquer les cadres précédemment affichés et affichent le cadre correspondant à la page demandée.
Après avoir créé nos différentes pages, il faut les construire, rajouter du texte, du champ de texte, etc. Tout d’abord, commence la page d’accueil, très simplement, on crée des blocs :
# création des "blocs" titre_acceuil = Label(cadre_acceuil, text="Bienvenue sur la base de données de la SPA", font=("Consolas", 20), bg="#C2C2C2", fg="black") soustitre_acceuil = Label(cadre_acceuil, text="DONNONS-LEUR AUTANT QU'ILS NOUS APPORTENT !", font=("Consolas", 13), bg="#C2C2C2", fg="black") # affichage de ces blocs titre_acceuil.pack(pady=20) soustitre_acceuil.pack()
Après cela, il ne nous reste plus qu’à créer les autres pages.
# création des different blocs + affichage des blocs titre_ajoute = Label(cadre_ajoute, text="AJOUTER", font=("Consolas", 20), bg="#C2C2C2", fg="black") titre_ajoute.pack(pady=20) soustitre_ajoute = Label(cadre_ajoute, text="Veuillez entrer les données de l'animal", font=("Consolas", 13), bg="#C2C2C2", fg="black") soustitre_ajoute.pack() desc_chmp_nom_str_ajoute = Label(cadre_ajoute, text="entrez son nom", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_chmp_nom_str_ajoute.pack() chmp_nom_str_ajoute = Entry(cadre_ajoute, font=("Helvetica",15), bg="#ffffff", fg="black", width=30) chmp_nom_str_ajoute.pack() desc_chmp_espece_str_ajoute = Label(cadre_ajoute, text="entrez son espèce", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_chmp_espece_str_ajoute.pack() chmp_espece_str_ajoute = Entry(cadre_ajoute, font=("Helvetica",15), bg="#ffffff", fg="black", width=30) chmp_espece_str_ajoute.pack() desc_chmp_race_str_ajoute = Label(cadre_ajoute, text="entrez sa race", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_chmp_race_str_ajoute.pack() chmp_race_str_ajoute = Entry(cadre_ajoute, font=("Helvetica",15), bg="#ffffff", fg="black", width=30) chmp_race_str_ajoute.pack() desc_chmp_age_str_ajoute = Label(cadre_ajoute, text="entrez son âge", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_chmp_age_str_ajoute.pack() chmp_age_str_ajoute = Entry(cadre_ajoute, font=("Helvetica",15), bg="#ffffff", fg="black", width=30) chmp_age_str_ajoute.pack() desc_chmp_localisation_str_ajoute = Label(cadre_ajoute, text="entrez le lieu où il a été trouvé", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_chmp_localisation_str_ajoute.pack() chmp_localisation_str_ajoute = Entry(cadre_ajoute, font=("Helvetica",15), bg="#ffffff", fg="black", width=30) chmp_localisation_str_ajoute.pack() #fonction pour ajouter les donnée choisies dans les champs de texte de la page ajouter dans la base de donnéee def ajouter_donnee(): connection = sqlite3.connect('base_SPA.db') curseur = connection.cursor() data = (chmp_nom_str_ajoute.get(),chmp_espece_str_ajoute.get(),chmp_race_str_ajoute.get(),chmp_age_str_ajoute.get(),chmp_localisation_str_ajoute.get()) curseur.execute("INSERT INTO ANNIMAL (nom,espèce,race,age,trouvé_où) VALUES (?,?,?,?,?)",data) connection.commit() curseur.close() connection.close() # création et placement du bouton utiliser pour valider l'ajout de donnée bouton_ajouter = Button(cadre_ajoute, text="Ajouter l'annimal", font=("Consolas",15), bg="white", fg="black",command = ajouter_donnee) bouton_ajouter.pack(pady=20)
Dans ce code, nous créons la fenêtre Ajouter avec les informations à remplir. Lorsque l’on clique sur le bouton Ajouter l’animal, celui ci sera ajouté automatiquement à la table de données.
# création des different blocs + affichage des blocs titre_modifier = Label(cadre_modifier, text="MODIFIER", font=("Consolas", 20), bg="#C2C2C2", fg="black") titre_modifier.pack(pady=20) desc_chmp_modifier = Label(cadre_modifier, text="entrez l'id de l'annimal", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_chmp_modifier.pack() chmp_str_modifier = Entry(cadre_modifier, font=("Helvetica",15), bg="#ffffff", fg="black", width=5) chmp_str_modifier.pack() # création de la liste déroulante desc_liste_deroul_modifier = Label(cadre_modifier, text="Choissisez quel donnée voulez vous modifier", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_liste_deroul_modifier.pack(pady=10) liste_choix = ["Nom","Race","Espèce","Age","Localisation"] liste_deroulante = ttk.Combobox(cadre_modifier, values=liste_choix) liste_deroulante.pack() desc_chmp2_modifier = Label(cadre_modifier, text="entrez la modification", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_chmp2_modifier.pack(pady=10) chmp2_str_modifier = Entry(cadre_modifier, font=("Helvetica",15), bg="#ffffff", fg="black", width=30) chmp2_str_modifier.pack() # fonction pour modifier une donnée dans la base de donnée à partir de la liste déroulante et le champ de texte def modifier_donnee(): select = liste_deroulante.get() datas = (chmp2_str_modifier.get(),chmp_str_modifier.get()) connection = sqlite3.connect('base_SPA.db') curseur = connection.cursor() if select == "Nom": curseur.execute("UPDATE ANNIMAL SET nom = ? WHERE id = ?",datas) if select == "Race": curseur.execute("UPDATE ANNIMAL SET race = ? WHERE id = ?",datas) if select == "Espèce": curseur.execute("UPDATE ANNIMAL SET espèce = ? WHERE id = ?",datas) if select == "Age": curseur.execute("UPDATE ANNIMAL SET age = ? WHERE id = ?",datas) if select == "Localisation": curseur.execute("UPDATE ANNIMAL SET trouvé_où = ? WHERE id = ?",datas) connection.commit() curseur.close() connection.close() # fonction pour supprimer toutes les données lié à un identifiant dans la base de donnée def supprimer_donnee(): sup_select = chmp_str_modifier.get() connection = sqlite3.connect('base_SPA.db') curseur = connection.cursor() curseur.execute("DELETE FROM ANNIMAL WHERE id = ?",sup_select) connection.commit() curseur.close() connection.close() # création et placement des boutons pour valider les modifications / suppressions bouton_sup = Button(cadre_modifier, text="Supprimer l'annimal ayant cet id", font=("Consolas",15), bg="white", fg="black", command = supprimer_donnee) bouton_sup.pack(pady=30) bouton_modifier = Button(cadre_modifier, text="Modifier", font=("Consolas",15), bg="white", fg="black", command = modifier_donnee) bouton_modifier.pack()
La fenêtre modifier quant à elle a besoin de l‘id de l’animal. En effet, pour modifier une information sur un animal, la personne doit rentrer l’id présente sur la table de donnée correspondant à l’animal, après cela, elle choisit l‘information à modifier dans la liste déroulante puis rentre la correction à faire. Ensuite, cette fenêtre abrite aussi la possibilité de supprimer l’animal comme cela a été dit précédemment grâce à la fonction supprimer_donnee() par l’id de l’animal.
# création des different blocs + affichage des blocs titre_parcourir = Label(cadre_parcourir, text="PARCOURIR", font=("Consolas", 20), bg="#C2C2C2", fg="black") titre_parcourir.pack(pady=10) desc_liste_deroulante_parcourir = Label(cadre_parcourir, text="Choississez par qu'elle type de donnee souhaitez vous rechercher", font=("Consolas", 13), bg="#C2C2C2", fg="black") desc_liste_deroulante_parcourir.pack(pady=10) # création de la liste déroulante du type de donnée liste_deroulante_parcourir = ttk.Combobox(cadre_parcourir, values=["id","Nom","Espèce", "Age","Race","Localisation"]) liste_deroulante_parcourir.set("id") liste_deroulante_parcourir.pack(pady=10) # création du cadre blanc où apparaissent les recherches effectuées frame_info_recherche = Frame(cadre_parcourir, bg="#C2C2C2",heigh = 50,width=650) frame_info_recherche.pack_propagate(False) frame_info_recherche.pack() desc_chmp_str_parcourir = Label(frame_info_recherche, text="écrivez cette information de recherche", font=("Consolas", 10), bg="#C2C2C2", fg="black") desc_chmp_str_parcourir.place(x=0,y=0) chmp_str_parcourir = Entry(frame_info_recherche, font=("Helvetica",10), bg="#ffffff", fg="black", width=15) chmp_str_parcourir.place(x=0,y=23) desc_chmp_str_parcourir = Label(frame_info_recherche, text="Si c'est une valeur elle doit être :", font=("Consolas", 10), bg="#C2C2C2", fg="black") desc_chmp_str_parcourir.place(x=390,y=0) # création de la liste déroulante pour préciser la recherche par valeurs numériques liste_deroulante_info_recherche = ttk.Combobox(frame_info_recherche, values=["=","<=",">=","<",">"],width=15) liste_deroulante_info_recherche.set("=") liste_deroulante_info_recherche.place(x=390,y=23) variable = StringVar() variable.set("1") chmp_str_info_recherche_parcourir = Entry(frame_info_recherche,textvariable=variable, font=("Helvetica",10), bg="#ffffff", fg="black", width=15) chmp_str_info_recherche_parcourir.place(x=510,y=23) # création de la variable qui stocke tout le résultat d'une recherche global recherche recherche = "" # fonction pour construire notre variable def parcourir_donnee(): global recherche recherche = "" connection = sqlite3.connect('base_SPA.db') curseur = connection.cursor() data = [chmp_str_parcourir.get()] data2 = [chmp_str_info_recherche_parcourir.get()] if liste_deroulante_parcourir.get() == "Nom": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE nom = ?",data).fetchall() if liste_deroulante_parcourir.get() == "Race": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE race = ?",data).fetchall() if liste_deroulante_parcourir.get() == "Espèce": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE espèce = ?",data).fetchall() if liste_deroulante_parcourir.get() == "Localisation": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE trouvé_où = ?",data).fetchall() if liste_deroulante_parcourir.get() == "Age": if liste_deroulante_info_recherche.get() == "=": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE age = ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == "<": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE age < ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == ">": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE age > ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == "<=": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE age <= ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == ">=": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE age >= ?",data2).fetchall() if liste_deroulante_parcourir.get() == "id": if liste_deroulante_info_recherche.get() == "=": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE id = ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == "<": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE id < ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == ">": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE id > ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == "<=": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE id <= ?",data2).fetchall() elif liste_deroulante_info_recherche.get() == ">=": recherche = curseur.execute("SELECT nom,espèce,race,age,trouvé_où FROM ANNIMAL WHERE id >= ?",data2).fetchall() connection.commit() curseur.close() connection.close() # fonction pour afficher la recherche sous une forme lisible def texte_parcourir(): texte_widget_frame_parcourir.delete("1.0","end") parcourir_donnee() for car in str(recherche): if car == "[" or car == "]" or car == "(" or car == "'" : texte_widget_frame_parcourir.insert(INSERT,"") elif car == ",": texte_widget_frame_parcourir.insert(INSERT,"") elif car == ")": texte_widget_frame_parcourir.insert(INSERT,"\n") else : texte_widget_frame_parcourir.insert(INSERT,car) # création et placement du bouton pour valider une recherche bouton_parcourir = Button(cadre_parcourir, text="Rechercher", font=("Consolas",15), bg="white", fg="black",command = texte_parcourir) bouton_parcourir.pack(pady=10) frame_parcourir = Frame(cadre_parcourir, bg="#ffffff",heigh = 210,width=650) frame_parcourir.pack_propagate(False) frame_parcourir.pack() # création et placement de la barre de scroll lié à la recherche effectuée scrollbar = Scrollbar(frame_parcourir, orient=VERTICAL) scrollbar.pack(side=RIGHT, fill=Y) texte_widget_frame_parcourir = Text(frame_parcourir, yscrollcommand=scrollbar.set) texte_widget_frame_parcourir.pack(fill=BOTH, expand=True) scrollbar = Scrollbar(texte_widget_frame_parcourir) scrollbar.config(command=texte_widget_frame_parcourir.yview) texte_recherche_parcourir = Text(frame_parcourir)
Dans ce code, nous créons la fenêtre Parcourir avec toutes ses informations.
Puis, finalement, on peut terminer le script :
# Affichage de la page d'accueil au lancement du script cadre_acceuil.pack() # Création du menu menubar = Menu(fenetre) # Ajout des commandes directement au menu principal menubar.add_command(label="Acceuil", command=affiche_acceuil) menubar.add_command(label="Ajouter", command=affiche_ajoute) menubar.add_command(label="Modifier", command=affiche_modifier) menubar.add_command(label="Parcourir", command=affiche_parcourir) # Configuration de la fenêtre avec la barre de menus fenetre.config(menu=menubar) # Initialisation de la pile des cadres cadre_pile = [cadre_acceuil] fenetre.mainloop()
Cette fin de script permet d’afficher l’interface et ses informations. Sans cela, Le script ne serait pas utilisable
III – Conclusion
Ainsi, ce projet nous a permis de mobiliser nos bases acquises en python et SQL pour monter un projet traitant sur les bases de données. Ce type de projet n’est pas des plus simples compte tenu de la technique à avoir et des difficultés rencontrées telles que le positionnement des blocs et les interactions avec la base de données. Pour continuer, il est important dans ce type de projets de comprendre son code ligne à ligne afin de ne pas se tromper sur un nom, une valeur ou autres.
Étudiant en spécialité NSI en classe de 1ère en 2022,
Streamer occasionnel.