Semaine 7
This commit is contained in:
1
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/.env
Normal file
1
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/.env
Normal file
@@ -0,0 +1 @@
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
@@ -0,0 +1 @@
|
||||
3.12
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
DB_HOST=localhost
|
||||
DB_USER=root
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
DB_NAME=petcare
|
||||
@@ -0,0 +1,23 @@
|
||||
from peewee import *
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
db_name = os.environ.get("DB_NAME")
|
||||
db_user = os.environ.get("DB_USER")
|
||||
db_password = os.environ.get("DB_PASSWORD")
|
||||
db_host = os.environ.get("DB_HOST")
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= 3306
|
||||
)
|
||||
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
@@ -0,0 +1,10 @@
|
||||
from __init__ import *
|
||||
|
||||
class Care(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 150, null= False)
|
||||
description = TextField()
|
||||
prix = DecimalField(max_digits= 6, decimal_places= 2)
|
||||
|
||||
class Meta:
|
||||
table_name = "traitement"
|
||||
@@ -0,0 +1,27 @@
|
||||
from __init__ import *
|
||||
from classes.pet import Pet
|
||||
from classes.veterinarian import Veterinarian
|
||||
from classes.care import Care
|
||||
|
||||
class Consultation(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
date_consultation = DateField(formats= '%Y-%m-%d') # formats= '%Y-%m-%d %H:%M:%S
|
||||
motif = CharField(max_length= 255, null= False)
|
||||
diagnostic = TextField()
|
||||
prix_consultation = DecimalField(max_digits= 6, decimal_places= 2)
|
||||
|
||||
animal = ForeignKeyField(Pet, backref= "animal", null= False)
|
||||
veterinaire = ForeignKeyField(Veterinarian, backref= "veterinaire", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "consultation"
|
||||
|
||||
class ConsultationCare(BaseModel):
|
||||
consultation = ForeignKeyField(Consultation)
|
||||
traitement = ForeignKeyField(Care)
|
||||
|
||||
class Meta:
|
||||
table_name = "consultation_traitement"
|
||||
indexes= (
|
||||
(("consultation", "traitement"), True),
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
from __init__ import *
|
||||
|
||||
class Owner(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
prenom = CharField(max_length= 100, null= False)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
telephone = CharField(max_length= 15, null= False)
|
||||
email = CharField(max_length= 150, null= False, unique= True)
|
||||
ville = CharField(max_length= 100, null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "proprietaire"
|
||||
@@ -0,0 +1,15 @@
|
||||
from __init__ import *
|
||||
from classes.owner import Owner
|
||||
|
||||
class Pet(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
espece = CharField(max_length= 50, null= False)
|
||||
race = CharField(max_length= 100, null= False)
|
||||
date_naissance = DateField(formats= '%Y-%m-%d')
|
||||
poids = DecimalField(max_digits= 5, decimal_places= 2)
|
||||
|
||||
proprietaire = ForeignKeyField(Owner, backref= "proprietaire", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "animal"
|
||||
@@ -0,0 +1,11 @@
|
||||
from __init__ import *
|
||||
|
||||
class Veterinarian(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
prenom = CharField(max_length= 100, null= False)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
specialite = CharField(max_length= 100, null= False, unique= True)
|
||||
telephone = CharField(max_length= 15, null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "veterinaire"
|
||||
@@ -0,0 +1,127 @@
|
||||
from __init__ import *
|
||||
|
||||
# 1. Modèles
|
||||
|
||||
from classes.care import *
|
||||
from classes.consultation import *
|
||||
from classes.owner import *
|
||||
from classes.pet import *
|
||||
from classes.veterinarian import *
|
||||
|
||||
# 2. CRUD
|
||||
|
||||
## 1. CREATE
|
||||
|
||||
try:
|
||||
with db.atomic():
|
||||
owner_01 = Owner.create(
|
||||
prenom= "Camille",
|
||||
nom= "LEMOINE",
|
||||
telephone= "0656781234",
|
||||
email= "camille.lemoine@mail.com",
|
||||
ville= "Bordeaux"
|
||||
)
|
||||
pet_01 = Pet.create(
|
||||
nom= "Pixel",
|
||||
espece= "Chat",
|
||||
race= "Bengal",
|
||||
date_naissance= "2023-06-15",
|
||||
poids= 4.5,
|
||||
proprietaire= owner_01
|
||||
)
|
||||
veterinarian_01_girard = Veterinarian.get(3)
|
||||
consultation_01 = Consultation.create(
|
||||
date_consultation= "2025-05-15",
|
||||
motif= "Première visite",
|
||||
diagnostic= "RAS",
|
||||
prix_consultation= 35.00,
|
||||
animal= pet_01,
|
||||
veterinaire= veterinarian_01_girard
|
||||
)
|
||||
|
||||
care_01_vermifuge = Care.get(Care.nom == "Vermifuge")
|
||||
care_01_puce_elec = Care.get(10)
|
||||
|
||||
ConsultationCare.create(consultation= consultation_01, traitement= care_01_vermifuge)
|
||||
ConsultationCare.create(consultation= consultation_01, traitement= care_01_puce_elec)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
|
||||
## 2. READ
|
||||
|
||||
print("\n----- Animaux de Claire MARTIN -----")
|
||||
claire_martin_pets = Pet.select().join(Owner).where(
|
||||
(Owner.prenom == "Claire") &
|
||||
(Owner.nom == "Martin")
|
||||
)
|
||||
for pet in claire_martin_pets:
|
||||
print(f"{pet.nom} - {pet.espece} - {pet.poids}")
|
||||
|
||||
print("\n----- Consultations de REX -----")
|
||||
claire_martin_rex_consultations = Consultation\
|
||||
.select(Consultation, Veterinarian)\
|
||||
.join(Veterinarian)\
|
||||
.where(Consultation.animal == 1)
|
||||
for consultation in claire_martin_rex_consultations:
|
||||
print(f"{consultation.date_consultation} - {consultation.motif} - Dr {consultation.veterinaire.nom}")
|
||||
|
||||
print("\n----- Statistiques par espèce -----")
|
||||
# Partie faite à l'aide de l'IA, notamment pour le "group_by" avant quoi je n'avais que "Chien" sans explication
|
||||
# et qui m'a soufflé l'idée de l'alias qui est quand même bien pratique
|
||||
stats_species = Pet.select(
|
||||
Pet.espece,
|
||||
fn.COUNT(Pet.id).alias("nb_pets"),
|
||||
fn.AVG(Pet.poids).alias("avg_weight")
|
||||
).group_by(Pet.espece)
|
||||
for stat in stats_species:
|
||||
print(f"{stat.nb_pets} {stat.espece}(s) au total - {round(stat.avg_weight, 2)}kg en moyenne")
|
||||
|
||||
## 3. UPDATE
|
||||
|
||||
print("\n----- Le Gros Buddy qui mange trop -----")
|
||||
try:
|
||||
pet_buddy = Pet.get(Pet.nom == "Buddy")
|
||||
print(f"Le poids de {pet_buddy.nom} est enregistré comme étant de {pet_buddy.poids}kg.")
|
||||
pet_buddy.poids = 29.50
|
||||
pet_buddy.save()
|
||||
print(f"Le poids de Buddy a été changé.")
|
||||
print(f"Le poids de {pet_buddy.nom} est enregistré comme étant de {pet_buddy.poids}kg.")
|
||||
except DoesNotExist:
|
||||
print("L'animal \"Buddy\" n'existe pas.")
|
||||
|
||||
## 4. DELETE
|
||||
|
||||
print("\n----- Vous z'avez pas vu mon fils ? -----")
|
||||
try:
|
||||
pet_nemo = Pet.get(Pet.nom == "Nemo")
|
||||
had_nemo_consultations = Consultation.select().where(Consultation.animal == pet_nemo).count()
|
||||
|
||||
if had_nemo_consultations > 0:
|
||||
print(f"Impossible de supprimer {pet_nemo.nom}, il possède des consultations associées.")
|
||||
else:
|
||||
pet_nemo.delete_instance()
|
||||
print(f"L'animal {pet_nemo.nom} a été supprimé de la base de données.")
|
||||
except DoesNotExist:
|
||||
print(f"L'animal \"Nemo\" n'a pas été trouvé dans la base de données.")
|
||||
|
||||
# 3. Requêtes avancées
|
||||
|
||||
print("\n----- Top 3 soigneurs de zanimaux -----")
|
||||
top_veterinarians = Veterinarian\
|
||||
.select(
|
||||
Veterinarian.nom,
|
||||
Veterinarian.specialite,
|
||||
fn.COUNT(Consultation.id).alias("nb_cons")
|
||||
)\
|
||||
.join(Consultation)\
|
||||
.group_by(Veterinarian.id)\
|
||||
.order_by(fn.COUNT(Consultation.id)\
|
||||
.desc()).limit(3)
|
||||
for idx, veterinarian in enumerate(top_veterinarians):
|
||||
print(f"{idx+1} - Dr {veterinarian.nom} avec {veterinarian.nb_cons} consultations.")
|
||||
|
||||
print("\n----- Facture n°1 détaillée -----")
|
||||
|
||||
|
||||
print("\n----- Historique-Animal -----")
|
||||
def historique_animal():
|
||||
@@ -0,0 +1,142 @@
|
||||
CREATE DATABASE IF NOT EXISTS petcare;
|
||||
USE petcare;
|
||||
|
||||
CREATE TABLE proprietaire (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
prenom VARCHAR(100) NOT NULL,
|
||||
telephone VARCHAR(15) NOT NULL,
|
||||
email VARCHAR(150) UNIQUE,
|
||||
ville VARCHAR(100) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE veterinaire (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
prenom VARCHAR(100) NOT NULL,
|
||||
specialite VARCHAR(100) NOT NULL,
|
||||
telephone VARCHAR(15) NOT NULL UNIQUE
|
||||
);
|
||||
|
||||
CREATE TABLE animal (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
espece VARCHAR(50) NOT NULL,
|
||||
race VARCHAR(100),
|
||||
date_naissance DATE,
|
||||
poids DECIMAL(5,2) CHECK (poids > 0),
|
||||
proprietaire_id INT NOT NULL,
|
||||
FOREIGN KEY (proprietaire_id) REFERENCES proprietaire(id)
|
||||
);
|
||||
|
||||
CREATE TABLE consultation (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
date_consultation DATE NOT NULL,
|
||||
motif VARCHAR(255) NOT NULL,
|
||||
diagnostic TEXT,
|
||||
prix_consultation DECIMAL(6,2) NOT NULL DEFAULT 35.00 CHECK (prix_consultation > 0),
|
||||
animal_id INT NOT NULL,
|
||||
veterinaire_id INT NOT NULL,
|
||||
FOREIGN KEY (animal_id) REFERENCES animal(id),
|
||||
FOREIGN KEY (veterinaire_id) REFERENCES veterinaire(id)
|
||||
);
|
||||
|
||||
CREATE TABLE traitement (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(150) NOT NULL,
|
||||
description TEXT,
|
||||
prix DECIMAL(6,2) NOT NULL CHECK (prix > 0)
|
||||
);
|
||||
|
||||
CREATE TABLE consultation_traitement (
|
||||
consultation_id INT,
|
||||
traitement_id INT,
|
||||
dosage VARCHAR(100),
|
||||
PRIMARY KEY (consultation_id, traitement_id),
|
||||
FOREIGN KEY (consultation_id) REFERENCES consultation(id),
|
||||
FOREIGN KEY (traitement_id) REFERENCES traitement(id)
|
||||
);
|
||||
|
||||
-- Propriétaires
|
||||
INSERT INTO proprietaire (nom, prenom, telephone, email, ville) VALUES
|
||||
('Martin', 'Claire', '0612345678', 'claire.martin@mail.com', 'Paris'),
|
||||
('Dupont', 'Jean', '0698765432', 'jean.dupont@mail.com', 'Lyon'),
|
||||
('Bernard', 'Sophie', '0654321987', 'sophie.bernard@mail.com', 'Paris'),
|
||||
('Petit', 'Thomas', '0687654321', 'thomas.petit@mail.com', 'Marseille'),
|
||||
('Moreau', 'Julie', '0676543210', 'julie.moreau@mail.com', 'Lyon'),
|
||||
('Garcia', 'Pierre', '0665432109', NULL, 'Toulouse'),
|
||||
('Roux', 'Isabelle', '0643219876', 'isabelle.roux@mail.com', 'Paris');
|
||||
|
||||
-- Vétérinaires
|
||||
INSERT INTO veterinaire (nom, prenom, specialite, telephone) VALUES
|
||||
('Leroy', 'Marc', 'Chirurgie', '0611111111'),
|
||||
('Fabre', 'Anne', 'Dermatologie', '0622222222'),
|
||||
('Girard', 'Paul', 'Médecine générale', '0633333333'),
|
||||
('Duval', 'Marie', 'Comportement', '0644444444');
|
||||
|
||||
-- Animaux
|
||||
INSERT INTO animal (nom, espece, race, date_naissance, poids, proprietaire_id) VALUES
|
||||
('Rex', 'Chien', 'Berger Allemand', '2020-03-15', 32.50, 1),
|
||||
('Mimi', 'Chat', 'Siamois', '2019-07-22', 4.20, 1),
|
||||
('Buddy', 'Chien', 'Labrador', '2021-01-10', 28.00, 2),
|
||||
('Luna', 'Chat', 'Persan', '2022-05-18', 3.80, 3),
|
||||
('Rocky', 'Chien', 'Bulldog', '2020-11-03', 22.50, 4),
|
||||
('Nemo', 'Poisson', 'Poisson clown', '2023-01-01', 0.02, 4),
|
||||
('Bella', 'Chien', 'Golden Retriever', '2019-09-14', 30.00, 5),
|
||||
('Caramel', 'Chat', 'Européen', '2021-08-25', 5.10, 5),
|
||||
('Max', 'Chien', 'Husky', '2022-02-28', 25.00, 6),
|
||||
('Coco', 'Perroquet', 'Ara', '2018-04-12', 1.20, 7),
|
||||
('Filou', 'Chat', 'Maine Coon', '2020-06-30', 7.50, 7),
|
||||
('Oscar', 'Chien', 'Caniche', '2023-03-20', 8.00, 2);
|
||||
|
||||
-- Traitements
|
||||
INSERT INTO traitement (nom, description, prix) VALUES
|
||||
('Vaccination rage', 'Vaccin antirabique annuel', 45.00),
|
||||
('Vaccination typhus', 'Vaccin contre le typhus félin', 40.00),
|
||||
('Vermifuge', 'Traitement antiparasitaire interne', 25.00),
|
||||
('Anti-puces', 'Traitement antiparasitaire externe', 30.00),
|
||||
('Détartrage', 'Nettoyage dentaire sous anesthésie', 80.00),
|
||||
('Radiographie', 'Examen radiologique', 60.00),
|
||||
('Analyse sanguine', 'Bilan sanguin complet', 55.00),
|
||||
('Antibiotiques', 'Traitement antibactérien 10 jours', 35.00),
|
||||
('Castration', 'Stérilisation chirurgicale', 120.00),
|
||||
('Puce électronique', 'Identification par puce', 50.00);
|
||||
|
||||
-- Consultations
|
||||
INSERT INTO consultation (date_consultation, motif, diagnostic, prix_consultation, animal_id, veterinaire_id) VALUES
|
||||
('2025-01-15', 'Visite annuelle', 'Bon état général', 35.00, 1, 1),
|
||||
('2025-01-20', 'Boiterie', 'Entorse légère patte avant droite', 35.00, 3, 1),
|
||||
('2025-02-10', 'Mauvaise haleine', 'Tartre important', 35.00, 2, 2),
|
||||
('2025-02-14', 'Perte de poils', 'Allergie alimentaire', 45.00, 4, 2),
|
||||
('2025-03-01', 'Vaccination', 'RAS', 35.00, 5, 3),
|
||||
('2025-03-05', 'Griffures', 'Infection cutanée légère', 35.00, 8, 2),
|
||||
('2025-03-10', 'Visite annuelle', 'Surpoids léger', 35.00, 7, 3),
|
||||
('2025-03-15', 'Apathie', 'Anémie légère', 45.00, 11, 3),
|
||||
('2025-04-01', 'Comportement agressif', 'Stress environnemental', 50.00, 9, 4),
|
||||
('2025-04-10', 'Visite annuelle', 'Bon état général', 35.00, 10, 3),
|
||||
('2025-04-15', 'Vomissements', 'Gastrite', 35.00, 12, 1),
|
||||
('2025-04-20', 'Visite de contrôle', 'Guérison confirmée', 35.00, 3, 1),
|
||||
('2025-05-01', 'Vaccination rappel', 'RAS', 35.00, 1, 3);
|
||||
|
||||
-- Consultations-Traitements
|
||||
INSERT INTO consultation_traitement (consultation_id, traitement_id, dosage) VALUES
|
||||
(1, 1, '1 injection'),
|
||||
(1, 3, '1 comprimé'),
|
||||
(2, 6, '2 clichés'),
|
||||
(2, 8, '1 comprimé/jour pendant 5 jours'),
|
||||
(3, 5, 'Séance complète'),
|
||||
(4, 7, 'Prélèvement standard'),
|
||||
(4, 4, 'Application locale'),
|
||||
(5, 1, '1 injection'),
|
||||
(5, 10, 'Implantation épaule gauche'),
|
||||
(6, 8, '1 comprimé/jour pendant 7 jours'),
|
||||
(6, 4, 'Application locale'),
|
||||
(7, 3, '1 comprimé'),
|
||||
(7, 7, 'Prélèvement standard'),
|
||||
(8, 7, 'Prélèvement standard'),
|
||||
(9, 7, 'Prélèvement standard'),
|
||||
(10, 3, '1 comprimé'),
|
||||
(11, 8, '1 comprimé/jour pendant 5 jours'),
|
||||
(12, 6, '1 cliché'),
|
||||
(13, 1, '1 injection'),
|
||||
(13, 3, '1 comprimé');
|
||||
@@ -0,0 +1,4 @@
|
||||
DB_HOST=localhost
|
||||
DB_USER=root
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
DB_NAME=datacenters
|
||||
@@ -0,0 +1,23 @@
|
||||
from peewee import *
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
db_name = os.environ.get("DB_NAME")
|
||||
db_user = os.environ.get("DB_USER")
|
||||
db_password = os.environ.get("DB_PASSWORD")
|
||||
db_host = os.environ.get("DB_HOST")
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= 3306
|
||||
)
|
||||
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
@@ -0,0 +1,11 @@
|
||||
from __init__ import *
|
||||
|
||||
class Client(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 150, null= False)
|
||||
email = CharField(max_length= 200, null= False)
|
||||
telephone = CharField(max_length= 20, null= False)
|
||||
type_contrat = CharField(max_length= 50, null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "client"
|
||||
@@ -0,0 +1,12 @@
|
||||
from __init__ import *
|
||||
|
||||
class Datacenter(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
ville = CharField(max_length= 100, null= False)
|
||||
pays = CharField(max_length= 100, null= False)
|
||||
capacite_racks = IntegerField(null= False)
|
||||
annee_ouverture = IntegerField(null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "datacenter"
|
||||
@@ -0,0 +1,15 @@
|
||||
from __init__ import *
|
||||
from classes.client import Client
|
||||
from classes.servers import Serveur
|
||||
|
||||
class Hebergement(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
date_debut = DateField(formats= "%Y-%m-%d", null= False)
|
||||
date_fin = DateField(formats= "%Y-%m-%d", null= True)
|
||||
prix_mensuel = DecimalField(max_digits= 8, decimal_places= 2, null= False)
|
||||
|
||||
serveur = ForeignKeyField(Serveur, backref= "serveur", null= False)
|
||||
client = ForeignKeyField(Client, backref= "client", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "hebergement"
|
||||
@@ -0,0 +1,15 @@
|
||||
from __init__ import *
|
||||
from classes.servers import Serveur
|
||||
|
||||
class Intervention(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
date_intervention = DateField(formats= "%Y-%m-%d")
|
||||
type_intervention = CharField(max_length= 100, null= False)
|
||||
description = TextField()
|
||||
duree_heures = DecimalField(max_digits= 4, decimal_places= 2, null= False)
|
||||
cout = DecimalField(max_digits= 8, decimal_places= 2, null= False)
|
||||
|
||||
serveur = ForeignKeyField(Serveur, backref= "serveur", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "intervention"
|
||||
@@ -0,0 +1,14 @@
|
||||
from __init__ import *
|
||||
from classes.datacenter import Datacenter
|
||||
|
||||
class Salle(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
etage = IntegerField(null= False)
|
||||
superficie_m2 = DecimalField(max_digits= 7, decimal_places= 2, null= False)
|
||||
nb_racks = IntegerField(null= False)
|
||||
|
||||
datacenter = ForeignKeyField(Datacenter, backref= "datacenter", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "salle"
|
||||
@@ -0,0 +1,17 @@
|
||||
from __init__ import *
|
||||
from classes.salle import Salle
|
||||
|
||||
class Serveur(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
hostname = CharField(max_length= 100, null= False)
|
||||
marque = CharField(max_length= 100, null= False)
|
||||
modele = CharField(max_length= 100, null= False)
|
||||
cpu_cores = IntegerField(null= False)
|
||||
ram_go = IntegerField(null= False)
|
||||
stockage_to = DecimalField(max_digits= 5, decimal_places= 2, null= False)
|
||||
date_installation = DateField(formats= "%Y-%m-%d")
|
||||
|
||||
salle = ForeignKeyField(Salle, backref= "salle", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "serveur"
|
||||
@@ -0,0 +1,115 @@
|
||||
from __init__ import *
|
||||
|
||||
from classes.client import *
|
||||
from classes.datacenter import *
|
||||
from classes.hosting import *
|
||||
from classes.intervention import *
|
||||
from classes.salle import *
|
||||
from classes.servers import *
|
||||
|
||||
# 1. Requêtes de base
|
||||
|
||||
print("\n----- Datacenters en France par année d'ouverture -----")
|
||||
datacenters_france = (Datacenter
|
||||
.select(Datacenter.nom, Datacenter.ville)
|
||||
.where(Datacenter.pays == "France")
|
||||
.order_by(Datacenter.annee_ouverture))
|
||||
for datacenter in datacenters_france:
|
||||
print(f"{datacenter.nom} - {datacenter.ville}")
|
||||
|
||||
print("\n----- Serveurs Dell par nom d'hôte -----")
|
||||
dell_servers = (Serveur
|
||||
.select(Serveur.hostname, Serveur.modele, Serveur.cpu_cores)
|
||||
.where(Serveur.marque == 'Dell')
|
||||
.order_by(Serveur.hostname))
|
||||
for serveur in dell_servers:
|
||||
print(f"{serveur.hostname} - Modèle {serveur.modele} - {serveur.cpu_cores} coeurs")
|
||||
|
||||
print("\n----- Interventions de mars 2025 -----")
|
||||
march_2025_interventions = (Intervention
|
||||
.select(Intervention.type_intervention, Intervention.cout, Intervention.date_intervention)
|
||||
.where(Intervention.date_intervention.between('2025-03-01', '2025-03-31')))
|
||||
for intervention in march_2025_interventions:
|
||||
print(f"{intervention.date_intervention} : {intervention.type_intervention} pour {intervention.cout}€.")
|
||||
|
||||
# 2. Jointures
|
||||
|
||||
print("\n----- Liste des serveurs -----")
|
||||
server_listing = (Serveur
|
||||
.select(Serveur, Salle, Datacenter)
|
||||
.join(Salle)
|
||||
.join(Datacenter)
|
||||
.order_by(Datacenter.nom, Serveur.hostname))
|
||||
for server in server_listing:
|
||||
print(f"{server.hostname} - Salle {server.salle.nom}, DC {server.salle.datacenter.nom}")
|
||||
|
||||
print("\n----- Hébergements actifs -----")
|
||||
active_hostings = (Hebergement
|
||||
.select(Hebergement, Client, Serveur)
|
||||
.join(Client)
|
||||
.switch(Hebergement)
|
||||
.join(Serveur)
|
||||
.where(Hebergement.date_fin.is_null())
|
||||
.order_by(Hebergement.prix_mensuel.desc()))
|
||||
for active_hosting in active_hostings:
|
||||
print(f"{active_hosting.client.nom} - sur {active_hosting.serveur.hostname} pour {active_hosting.prix_mensuel}€ / mois.")
|
||||
|
||||
print("\n----- Serveurs qui n'ont jamais panné (ni poisson ni rien) -----")
|
||||
servers_without_problem = (Serveur
|
||||
.select(Serveur.hostname, Serveur.date_installation)
|
||||
.join(Intervention, JOIN.LEFT_OUTER)
|
||||
.where(Intervention.id.is_null()))
|
||||
for server in servers_without_problem:
|
||||
print(f"{server.hostname} - Installation {server.date_installation}.)")
|
||||
|
||||
print("\n----- Hébergements par client -----")
|
||||
client_hostings = (Client
|
||||
.select(Client.nom,
|
||||
fn.COUNT(Hebergement.id).alias("nb_servers"),
|
||||
fn.SUM(Hebergement.prix_mensuel).alias("monthly_price"))
|
||||
.join(Hebergement)
|
||||
.group_by(Client.id, Client.nom)
|
||||
.order_by(fn.SUM(Hebergement.prix_mensuel).desc()))
|
||||
for client_hosting in client_hostings:
|
||||
total = client_hosting.monthly_price if client_hosting.monthly_price else 0
|
||||
print(f"{client_hosting.nom} - {client_hosting.nb_servers} serveur(s) pour un total de {total}€ / mois.")
|
||||
|
||||
# 3. Agrégations
|
||||
|
||||
print("\n----- Liste des serveurs par marque -----")
|
||||
servers_brand = (Serveur
|
||||
.select(Serveur.marque, fn.COUNT(Serveur.id).alias("nb_servers"))
|
||||
.group_by(Serveur.marque))
|
||||
for server_brand in servers_brand:
|
||||
print(f"{server_brand.marque} - {server_brand.nb_servers} serveur(s).")
|
||||
|
||||
print("\n----- Coût total par intervention -----")
|
||||
intervention_cost = (Intervention
|
||||
.select(Intervention.type_intervention,
|
||||
fn.SUM(Intervention.cout).alias("cost"),
|
||||
fn.AVG(Intervention.cout).alias("avg"))
|
||||
.group_by(Intervention.type_intervention))
|
||||
for cost in intervention_cost:
|
||||
print(f"{cost.type_intervention} - {cost.cost}€ - moyenne à {round(cost.avg, 2)}€.") # Bonus pour le fun
|
||||
|
||||
print("\n----- Datacenters qui tournent pas trop à vide -----")
|
||||
empty_datacenters = (Datacenter
|
||||
.select(Datacenter.nom, fn.COUNT(Serveur.id).alias("nb_serveurs"))
|
||||
.join(Salle)
|
||||
.join(Serveur)
|
||||
.group_by(Datacenter.id, Datacenter.nom)
|
||||
.having(fn.COUNT(Serveur.id) > 3))
|
||||
for datacenter in empty_datacenters:
|
||||
print(f"{datacenter.nom} - {datacenter.nb_serveurs} serveurs.")
|
||||
|
||||
print("\n----- Mois le plus chargé de l'année -----")
|
||||
heaviest_month = (Intervention
|
||||
.select(fn.DATE_FORMAT(Intervention.date_intervention, '%Y-%m').alias('mois'),
|
||||
fn.COUNT(Intervention.id).alias('nb_interventions'),
|
||||
fn.SUM(Intervention.cout).alias('cout_total'))
|
||||
.group_by(fn.DATE_FORMAT(Intervention.date_intervention, '%Y-%m'))
|
||||
.order_by(fn.COUNT(Intervention.id).desc())
|
||||
.limit(1))
|
||||
for record in heaviest_month:
|
||||
print(f"En {record.mois}, il y a eu {record.nb_interventions} interventions totalisant {record.cout_total}€.\n\
|
||||
Pensez aux actionnaires !")
|
||||
@@ -0,0 +1,152 @@
|
||||
CREATE DATABASE IF NOT EXISTS datacenters;
|
||||
USE datacenters;
|
||||
|
||||
CREATE TABLE datacenter (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL UNIQUE,
|
||||
ville VARCHAR(100) NOT NULL,
|
||||
pays VARCHAR(100) NOT NULL,
|
||||
capacite_racks INT NOT NULL CHECK (capacite_racks > 0),
|
||||
annee_ouverture INT NOT NULL CHECK (annee_ouverture >= 2000)
|
||||
);
|
||||
|
||||
CREATE TABLE salle (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
etage INT NOT NULL,
|
||||
superficie_m2 DECIMAL(7,2) NOT NULL CHECK (superficie_m2 > 0),
|
||||
nb_racks INT NOT NULL CHECK (nb_racks > 0),
|
||||
datacenter_id INT NOT NULL,
|
||||
FOREIGN KEY (datacenter_id) REFERENCES datacenter(id)
|
||||
);
|
||||
|
||||
CREATE TABLE client (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(150) NOT NULL,
|
||||
email VARCHAR(200) NOT NULL UNIQUE,
|
||||
telephone VARCHAR(20),
|
||||
type_contrat VARCHAR(50) NOT NULL CHECK (type_contrat IN ('Essentiel', 'Standard', 'Premium'))
|
||||
);
|
||||
|
||||
CREATE TABLE serveur (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
hostname VARCHAR(100) NOT NULL UNIQUE,
|
||||
marque VARCHAR(100) NOT NULL,
|
||||
modele VARCHAR(100) NOT NULL,
|
||||
cpu_cores INT NOT NULL CHECK (cpu_cores > 0),
|
||||
ram_go INT NOT NULL CHECK (ram_go > 0),
|
||||
stockage_to DECIMAL(5,2) NOT NULL CHECK (stockage_to > 0),
|
||||
date_installation DATE NOT NULL,
|
||||
salle_id INT NOT NULL,
|
||||
FOREIGN KEY (salle_id) REFERENCES salle(id)
|
||||
);
|
||||
|
||||
CREATE TABLE intervention (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
date_intervention DATE NOT NULL,
|
||||
type_intervention VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
duree_heures DECIMAL(4,2) NOT NULL CHECK (duree_heures > 0),
|
||||
cout DECIMAL(8,2) NOT NULL CHECK (cout >= 0),
|
||||
serveur_id INT NOT NULL,
|
||||
FOREIGN KEY (serveur_id) REFERENCES serveur(id)
|
||||
);
|
||||
|
||||
CREATE TABLE hebergement (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
date_debut DATE NOT NULL,
|
||||
date_fin DATE,
|
||||
prix_mensuel DECIMAL(8,2) NOT NULL CHECK (prix_mensuel > 0),
|
||||
serveur_id INT NOT NULL,
|
||||
client_id INT NOT NULL,
|
||||
FOREIGN KEY (serveur_id) REFERENCES serveur(id),
|
||||
FOREIGN KEY (client_id) REFERENCES client(id)
|
||||
);
|
||||
|
||||
-- Datacenters
|
||||
INSERT INTO datacenter (nom, ville, pays, capacite_racks, annee_ouverture) VALUES
|
||||
('DC-Paris-Nord', 'Paris', 'France', 500, 2015),
|
||||
('DC-Lyon-Est', 'Lyon', 'France', 300, 2018),
|
||||
('DC-Marseille-Sud', 'Marseille', 'France', 200, 2020),
|
||||
('DC-Bruxelles-Centre', 'Bruxelles', 'Belgique', 400, 2016),
|
||||
('DC-Geneve-Lac', 'Genève', 'Suisse', 250, 2019);
|
||||
|
||||
-- Salles
|
||||
INSERT INTO salle (nom, etage, superficie_m2, nb_racks, datacenter_id) VALUES
|
||||
('Salle Alpha', 0, 450.00, 120, 1),
|
||||
('Salle Beta', 0, 380.00, 100, 1),
|
||||
('Salle Gamma', 1, 500.00, 140, 1),
|
||||
('Salle Delta', 0, 300.00, 80, 2),
|
||||
('Salle Epsilon', 1, 280.00, 70, 2),
|
||||
('Salle Zeta', 0, 200.00, 50, 3),
|
||||
('Salle Eta', 0, 350.00, 100, 4),
|
||||
('Salle Theta', 1, 320.00, 90, 4),
|
||||
('Salle Iota', 0, 250.00, 65, 5),
|
||||
('Salle Kappa', 1, 230.00, 60, 5);
|
||||
|
||||
-- Clients
|
||||
INSERT INTO client (nom, email, telephone, type_contrat) VALUES
|
||||
('TechnoWeb SAS', 'contact@technoweb.fr', '0145678901', 'Premium'),
|
||||
('StartupFlow', 'admin@startupflow.io', '0234567890', 'Standard'),
|
||||
('MegaStore Europe', 'infra@megastore.eu', '0156789012', 'Premium'),
|
||||
('DataLab Research', 'tech@datalab.org', '0145671234', 'Standard'),
|
||||
('CloudFirst Agency', 'ops@cloudfirst.fr', '0198765432', 'Premium'),
|
||||
('GreenEnergy Corp', 'it@greenenergy.com', '0187654321', 'Essentiel'),
|
||||
('MediaPlus', 'support@mediaplus.fr', '0176543210', 'Standard'),
|
||||
('FinanceSecure SA', 'infra@financesecure.ch', '0223456789', 'Premium'),
|
||||
('EduConnect', 'admin@educonnect.fr', '0156784321', 'Essentiel'),
|
||||
('LogiTrans SARL', 'it@logitrans.fr', '0167890123', 'Standard');
|
||||
|
||||
-- Serveurs
|
||||
INSERT INTO serveur (hostname, marque, modele, cpu_cores, ram_go, stockage_to, date_installation, salle_id) VALUES
|
||||
('srv-web-01', 'Dell', 'PowerEdge R750', 32, 128, 2.00, '2023-03-15', 1),
|
||||
('srv-web-02', 'Dell', 'PowerEdge R750', 32, 128, 2.00, '2023-03-15', 1),
|
||||
('srv-db-01', 'HP', 'ProLiant DL380', 64, 512, 8.00, '2022-06-10', 1),
|
||||
('srv-app-01', 'Lenovo', 'ThinkSystem SR650', 48, 256, 4.00, '2023-09-01', 2),
|
||||
('srv-storage-01', 'Dell', 'PowerEdge R760', 16, 64, 24.00, '2024-01-20', 3),
|
||||
('srv-lyon-01', 'HP', 'ProLiant DL360', 32, 128, 2.00, '2023-05-12', 4),
|
||||
('srv-lyon-02', 'HP', 'ProLiant DL380', 48, 256, 4.00, '2022-11-08', 4),
|
||||
('srv-lyon-db-01', 'Dell', 'PowerEdge R750', 64, 512, 8.00, '2023-01-25', 5),
|
||||
('srv-mars-01', 'Lenovo', 'ThinkSystem SR630', 16, 64, 1.00, '2024-03-10', 6),
|
||||
('srv-mars-02', 'Lenovo', 'ThinkSystem SR650', 32, 128, 2.00, '2024-03-10', 6),
|
||||
('srv-brux-01', 'Dell', 'PowerEdge R750', 48, 256, 4.00, '2021-07-15', 7),
|
||||
('srv-brux-02', 'HP', 'ProLiant DL380', 64, 512, 8.00, '2021-07-15', 7),
|
||||
('srv-brux-03', 'Dell', 'PowerEdge R760', 32, 128, 2.00, '2023-04-20', 8),
|
||||
('srv-gen-01', 'HP', 'ProLiant DL380', 48, 256, 4.00, '2022-09-05', 9),
|
||||
('srv-gen-02', 'Lenovo', 'ThinkSystem SR650', 32, 128, 2.00, '2023-08-18', 10);
|
||||
|
||||
-- Interventions
|
||||
INSERT INTO intervention (date_intervention, type_intervention, description, duree_heures, cout, serveur_id) VALUES
|
||||
('2025-01-10', 'Maintenance préventive', 'Remplacement disques préventif', 2.00, 350.00, 3),
|
||||
('2025-01-15', 'Panne matérielle', 'Remplacement alimentation défectueuse', 1.50, 280.00, 1),
|
||||
('2025-02-01', 'Mise à jour firmware', 'Update BIOS et firmware RAID', 1.00, 150.00, 6),
|
||||
('2025-02-12', 'Panne matérielle', 'Remplacement barrette RAM défectueuse', 0.50, 420.00, 12),
|
||||
('2025-02-20', 'Extension capacité', 'Ajout 256 Go RAM', 1.00, 1200.00, 7),
|
||||
('2025-03-01', 'Maintenance préventive', 'Nettoyage et vérification câblage', 3.00, 200.00, 11),
|
||||
('2025-03-05', 'Mise à jour firmware', 'Update BIOS', 0.50, 100.00, 4),
|
||||
('2025-03-10', 'Panne matérielle', 'Remplacement ventilateur', 0.50, 180.00, 9),
|
||||
('2025-03-15', 'Extension capacité', 'Ajout disque SSD 2 To', 1.00, 450.00, 14),
|
||||
('2025-04-01', 'Maintenance préventive', 'Vérification générale', 2.00, 200.00, 1),
|
||||
('2025-04-05', 'Panne matérielle', 'Remplacement contrôleur RAID', 2.50, 750.00, 8),
|
||||
('2025-04-10', 'Mise à jour firmware', 'Update firmware stockage', 1.00, 150.00, 5),
|
||||
('2025-04-15', 'Maintenance préventive', 'Remplacement pâte thermique CPU', 1.50, 120.00, 13),
|
||||
('2025-05-01', 'Panne matérielle', 'Remplacement carte réseau', 1.00, 320.00, 2),
|
||||
('2025-05-10', 'Extension capacité', 'Ajout 128 Go RAM', 0.50, 600.00, 10);
|
||||
|
||||
-- Hébergements
|
||||
INSERT INTO hebergement (date_debut, date_fin, prix_mensuel, serveur_id, client_id) VALUES
|
||||
('2023-04-01', NULL, 850.00, 1, 1),
|
||||
('2023-04-01', NULL, 850.00, 2, 1),
|
||||
('2022-07-01', NULL, 1500.00, 3, 3),
|
||||
('2023-10-01', NULL, 1100.00, 4, 5),
|
||||
('2024-02-01', NULL, 600.00, 5, 3),
|
||||
('2023-06-01', '2025-01-31', 750.00, 6, 2),
|
||||
('2023-02-01', NULL, 1100.00, 7, 4),
|
||||
('2023-02-01', NULL, 1500.00, 8, 8),
|
||||
('2024-04-01', NULL, 400.00, 9, 9),
|
||||
('2024-04-01', NULL, 750.00, 10, 6),
|
||||
('2021-08-01', NULL, 1100.00, 11, 3),
|
||||
('2021-08-01', NULL, 1500.00, 12, 8),
|
||||
('2023-05-01', NULL, 750.00, 13, 7),
|
||||
('2022-10-01', NULL, 1100.00, 14, 5),
|
||||
('2023-09-01', NULL, 750.00, 15, 10);
|
||||
47
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/README.md
Normal file
47
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Evaluation 20/03/2026 - BOICHÉ Gauvain
|
||||
|
||||
## Démarrage
|
||||
|
||||
### Initialisation
|
||||
|
||||
```bash
|
||||
uv init --python 3.12
|
||||
uv run main.py
|
||||
.venv/Scripts/activate
|
||||
|
||||
uv add dotenv
|
||||
uv add peewee pymysql
|
||||
```
|
||||
|
||||
### Fichier .env
|
||||
|
||||
Les "secrets" sont gérés pour l'occasion dans un fichier .env
|
||||
|
||||
Normalement, on met aussi un fichier
|
||||
|
||||
`.gitignore`
|
||||
|
||||
Dont le contenu mentionne :
|
||||
|
||||
`*.env`
|
||||
|
||||
Pour l'exercice évidemment, je garde le fichier en clair.
|
||||
|
||||
## Partie 1
|
||||
|
||||
|
||||
|
||||
## Partie 2
|
||||
|
||||
### Requêtes normales
|
||||
|
||||
Avoir une requête SQL normale fonctionne :
|
||||
|
||||
```sql
|
||||
select nom, ville
|
||||
from datacenters.datacenter
|
||||
where pays = "France"
|
||||
order by annee_ouverture;
|
||||
```
|
||||
|
||||
Maintenant faut les traduire.
|
||||
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: mysql_evaluation
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||||
command: --log_bin_trust_function_creators=1
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
[project]
|
||||
name = "boiche-gauvain-eval-20-03-2026"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"dotenv>=0.9.9",
|
||||
"peewee>=4.0.2",
|
||||
"pymysql>=1.1.2",
|
||||
]
|
||||
58
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/uv.lock
generated
Normal file
58
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/uv.lock
generated
Normal file
@@ -0,0 +1,58 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "boiche-gauvain-eval-20-03-2026"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "dotenv" },
|
||||
{ name = "peewee" },
|
||||
{ name = "pymysql" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "dotenv", specifier = ">=0.9.9" },
|
||||
{ name = "peewee", specifier = ">=4.0.2" },
|
||||
{ name = "pymysql", specifier = ">=1.1.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.9.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "python-dotenv" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/b7/545d2c10c1fc15e48653c91efde329a790f2eecfbbf2bd16003b5db2bab0/dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9", size = 1892, upload-time = "2025-02-19T22:15:01.647Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peewee"
|
||||
version = "4.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/54/9b/3439dcc3ed5138eb26f28fc208f958ca97b831f5f898b26d5354302e5df4/peewee-4.0.2.tar.gz", hash = "sha256:fd5d026ce7787c6cd3a84316e665a76b72c9c4e87322598c413f44604fa6c38d", size = 714081, upload-time = "2026-03-15T15:46:30.049Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/8e/943f57ce32eb005c7037110a759e2ebfb22e467a9a0efcb6d516c5bf00c6/peewee-4.0.2-py3-none-any.whl", hash = "sha256:86d5d16bcda5bbe017a108f6efc57abaac8d89277915541904542df9d2a7f25d", size = 143344, upload-time = "2026-03-15T15:46:28.778Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymysql"
|
||||
version = "1.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/ae/1fe3fcd9f959efa0ebe200b8de88b5a5ce3e767e38c7ac32fb179f16a388/pymysql-1.1.2.tar.gz", hash = "sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03", size = 48258, upload-time = "2025-08-24T12:55:55.146Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl", hash = "sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9", size = 45300, upload-time = "2025-08-24T12:55:53.394Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
|
||||
]
|
||||
5
Semaine_07/Jour_05/orm_peewee/.env
Normal file
5
Semaine_07/Jour_05/orm_peewee/.env
Normal file
@@ -0,0 +1,5 @@
|
||||
DB_HOST=localhost
|
||||
DB_USER=root
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
DB_NAME=company
|
||||
DB_PORT=3306
|
||||
1
Semaine_07/Jour_05/orm_peewee/.python-version
Normal file
1
Semaine_07/Jour_05/orm_peewee/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.12
|
||||
11
Semaine_07/Jour_05/orm_peewee/README.md
Normal file
11
Semaine_07/Jour_05/orm_peewee/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Normalement, on met aussi un fichier
|
||||
|
||||
`.gitignore`
|
||||
|
||||
Dont le contenu mentionne :
|
||||
|
||||
```
|
||||
*.env
|
||||
```
|
||||
|
||||
Pour l'exercice évidemment, je garde le fichier en clair.
|
||||
19
Semaine_07/Jour_05/orm_peewee/docker-compose.yml
Normal file
19
Semaine_07/Jour_05/orm_peewee/docker-compose.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: mysql_peewee
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||||
command: --log_bin_trust_function_creators=1
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
123
Semaine_07/Jour_05/orm_peewee/main.py
Normal file
123
Semaine_07/Jour_05/orm_peewee/main.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from peewee import *
|
||||
|
||||
# import os
|
||||
# from dotenv import load_dotenv
|
||||
|
||||
# load_dotenv()
|
||||
|
||||
# db_name = os.environ.get("DB_NAME")
|
||||
# db_user = os.environ.get("DB_USER")
|
||||
# db_password = os.environ.get("DB_PASSWORD")
|
||||
# db_host = os.environ.get("DB_HOST")
|
||||
# db_port = os.environ.get("DB_PORT")
|
||||
|
||||
db_name = "company"
|
||||
db_user = "root"
|
||||
db_password = "MementoMarsouin96"
|
||||
db_host = "localhost"
|
||||
db_port = 3306
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= db_port
|
||||
)
|
||||
|
||||
# équivalent de "Base = declarative_base()"
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
class Department(BaseModel):
|
||||
department_id = AutoField(primary_key= True)
|
||||
department_name = CharField(max_length= 50, null= False, unique= True)
|
||||
location_id = DecimalField(max_digits= 4, decimal_places= 0, null= False)
|
||||
|
||||
# équivalent de "__tablename__ = "truc""
|
||||
class Meta:
|
||||
table_name = "departments"
|
||||
|
||||
class Employee(BaseModel):
|
||||
employee_id = AutoField(primary_key= True)
|
||||
first_name = CharField(max_length= 50, null= False)
|
||||
last_name = CharField(max_length= 50, null= False)
|
||||
email = CharField(max_length= 50, null= False, unique= True)
|
||||
salary = IntegerField(null= False)
|
||||
|
||||
department = ForeignKeyField(Department, backref= "employees", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "employees"
|
||||
|
||||
db.connect()
|
||||
db.create_tables([Department, Employee])
|
||||
|
||||
try:
|
||||
it_dept = Department.create(department_name= "IT", location_id= 1400)
|
||||
except IntegrityError:
|
||||
print("Département déjà existant.")
|
||||
|
||||
it_dept = Department.get(Department.department_name == "IT")
|
||||
|
||||
try:
|
||||
Employee.create(
|
||||
first_name= "Alice",
|
||||
last_name= "Smith",
|
||||
email= "a.smith@company.au",
|
||||
salary= 4000,
|
||||
department= it_dept # utiliser l'OBJET, pas le nom de l'objet
|
||||
)
|
||||
except IntegrityError:
|
||||
print("Employé(e) déjà existant(e).")
|
||||
|
||||
new_employees = [
|
||||
{'first_name': 'Marie', 'last_name': 'Dupont', 'email': 'mdupont', 'salary': 4500},
|
||||
{'first_name': 'Jean', 'last_name': 'Martin', 'email': 'jmartin', 'salary': 5200},
|
||||
{'first_name': 'Sophie', 'last_name': 'Bernard', 'email': 'sbernard', 'salary': 4800},
|
||||
]
|
||||
|
||||
# with db.atomic():
|
||||
# Employee.insert_many(new_employees).execute()
|
||||
|
||||
employee_01 = Employee.get(1)
|
||||
print(employee_01.first_name, employee_01.last_name)
|
||||
|
||||
employee_02 = Employee.get(Employee.email == "a.smith@company.au")
|
||||
print(employee_02.first_name, employee_02.salary)
|
||||
|
||||
try:
|
||||
employee_76 = Employee.get(76)
|
||||
except DoesNotExist:
|
||||
print("L'employé(e) 76 n'existe pas.")
|
||||
|
||||
employee_select_01 = Employee.select() # SELECT * FROM employees
|
||||
print(employee_select_01)
|
||||
for employee in employee_select_01:
|
||||
print(employee.first_name, employee.last_name, employee.email)
|
||||
|
||||
employee_select_02 = Employee.select().where(
|
||||
(Employee.salary > 8000) & (Employee.department == it_dept)
|
||||
)
|
||||
print(employee_select_02)
|
||||
|
||||
# pagination
|
||||
page_01 = Employee.select().order_by(Employee.employee_id).paginate(1, 10)
|
||||
|
||||
# compter une valeur
|
||||
salary_01 = Employee.select().where(Employee.salary > 10000).count()
|
||||
|
||||
# Jointures (LEFT JOIN, RIGHT JOIN etc)
|
||||
### FULL JOIN
|
||||
query = (Employee
|
||||
.select(Employee, Department)
|
||||
.join(Department)
|
||||
.where(Department.department_name == "IT"))
|
||||
|
||||
### Employés affectés à un département
|
||||
### et ceux non affectés à un département
|
||||
query = (Employee
|
||||
.select(Employee, Department)
|
||||
.join(Department, JOIN.LEFT_OUTER)
|
||||
.where(Department.department_name == "IT"))
|
||||
10
Semaine_07/Jour_05/orm_peewee/pyproject.toml
Normal file
10
Semaine_07/Jour_05/orm_peewee/pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[project]
|
||||
name = "orm-peewee"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"peewee>=4.0.2",
|
||||
"pymysql>=1.1.2",
|
||||
]
|
||||
105
Semaine_07/Jour_05/orm_peewee/relations.py
Normal file
105
Semaine_07/Jour_05/orm_peewee/relations.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from peewee import *
|
||||
|
||||
# import os
|
||||
# from dotenv import load_dotenv
|
||||
|
||||
# load_dotenv()
|
||||
|
||||
# db_name = os.environ.get("DB_NAME")
|
||||
# db_user = os.environ.get("DB_USER")
|
||||
# db_password = os.environ.get("DB_PASSWORD")
|
||||
# db_host = os.environ.get("DB_HOST")
|
||||
# db_port = os.environ.get("DB_PORT")
|
||||
|
||||
db_name = "company"
|
||||
db_user = "root"
|
||||
db_password = "MementoMarsouin96"
|
||||
db_host = "localhost"
|
||||
db_port = 3306
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= db_port
|
||||
)
|
||||
|
||||
# équivalent de "Base = declarative_base()"
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
# Relations One-To-Many
|
||||
class User(BaseModel):
|
||||
username = CharField(unique= True)
|
||||
email = CharField()
|
||||
|
||||
class Meta:
|
||||
table_name = "user"
|
||||
|
||||
class Todo(BaseModel):
|
||||
title = CharField()
|
||||
is_done = BooleanField(default= False)
|
||||
user= ForeignKeyField(User, backref= "todos") # l'accès inverse est géré automatiquement
|
||||
|
||||
class Meta:
|
||||
table_name = "todos"
|
||||
|
||||
class Tag(BaseModel):
|
||||
name = CharField(unique= True)
|
||||
|
||||
class Meta:
|
||||
table_name = "tag"
|
||||
|
||||
class TodoTag(BaseModel):
|
||||
todo = ForeignKeyField(Todo)
|
||||
tag = ForeignKeyField(Tag)
|
||||
|
||||
class Meta:
|
||||
table_name = 'todo_tag'
|
||||
indexes= (
|
||||
(('todo', 'tag'), True),
|
||||
)
|
||||
|
||||
class Profile(BaseModel):
|
||||
user = ForeignKeyField(User, unique= True, backref= "profile") # One-To-One
|
||||
bio = TextField(null= True)
|
||||
avatar = CharField(null= True)
|
||||
|
||||
class Meta:
|
||||
table_name = "profile"
|
||||
|
||||
db.connect()
|
||||
db.create_tables([User, Todo, Profile, Tag, TodoTag])
|
||||
|
||||
try:
|
||||
alice = User.create(username= "Alice", email= "a.smith@company.au")
|
||||
Todo.create(title= "Apprendre Python", user= alice)
|
||||
Todo.create(title= "Apprendre JS", user= alice)
|
||||
Todo.create(title= "Apprendre COBOL", user= alice)
|
||||
|
||||
for todo in alice.todos:
|
||||
print(todo.title, todo.is_done)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
|
||||
try:
|
||||
Profile.create(
|
||||
user= User.get(1),
|
||||
bio = 'Developpeur',
|
||||
avatar= 'http://example.com'
|
||||
)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
|
||||
try:
|
||||
tag_urgent = Tag.create(name= "Urgent")
|
||||
tag_perso = Tag.create(name= "Perso")
|
||||
tag_pro = Tag.create(name= "Pro")
|
||||
|
||||
todo_cobol = Todo.get(Todo.title == "Apprendre COBOL")
|
||||
|
||||
TodoTag.create(todo= todo_cobol, tag= tag_urgent)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
36
Semaine_07/Jour_05/orm_peewee/uv.lock
generated
Normal file
36
Semaine_07/Jour_05/orm_peewee/uv.lock
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "orm-peewee"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "peewee" },
|
||||
{ name = "pymysql" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "peewee", specifier = ">=4.0.2" },
|
||||
{ name = "pymysql", specifier = ">=1.1.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peewee"
|
||||
version = "4.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/54/9b/3439dcc3ed5138eb26f28fc208f958ca97b831f5f898b26d5354302e5df4/peewee-4.0.2.tar.gz", hash = "sha256:fd5d026ce7787c6cd3a84316e665a76b72c9c4e87322598c413f44604fa6c38d", size = 714081, upload-time = "2026-03-15T15:46:30.049Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/8e/943f57ce32eb005c7037110a759e2ebfb22e467a9a0efcb6d516c5bf00c6/peewee-4.0.2-py3-none-any.whl", hash = "sha256:86d5d16bcda5bbe017a108f6efc57abaac8d89277915541904542df9d2a7f25d", size = 143344, upload-time = "2026-03-15T15:46:28.778Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymysql"
|
||||
version = "1.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/ae/1fe3fcd9f959efa0ebe200b8de88b5a5ce3e767e38c7ac32fb179f16a388/pymysql-1.1.2.tar.gz", hash = "sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03", size = 48258, upload-time = "2025-08-24T12:55:55.146Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl", hash = "sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9", size = 45300, upload-time = "2025-08-24T12:55:53.394Z" },
|
||||
]
|
||||
Reference in New Issue
Block a user