def homepage(order_by, id_horaire_sel): if request.method == "GET": try: try: # Renvoie une erreur si la connexion est perdue. MaBaseDeDonnee().connexion_bd.ping(False) except Exception as erreur: flash( f"Dans Gestion genres ...terrible erreur, il faut connecter une base de donnée", "danger") print( f"Exception grave Classe constructeur GestionGenres {erreur.args[0]}" ) raise MaBdErreurConnexion( f"{msg_erreurs['ErreurConnexionBD']['message']} {erreur.args[0]}" ) with MaBaseDeDonnee().connexion_bd.cursor() as mc_afficher: if order_by == "ASC" and id_horaire_sel == 0: strsql_horaire_afficher = """SELECT id_horaires, date_et_heure_horaires FROM t_horaires ORDER BY id_horaires ASC""" mc_afficher.execute(strsql_horaire_afficher) elif order_by == "ASC": # C'EST LA QUE VOUS ALLEZ DEVOIR PLACER VOTRE PROPRE LOGIQUE MySql # la commande MySql classique est "SELECT * FROM t_genre" # Pour "lever"(raise) une erreur s'il y a des erreurs sur les noms d'attributs dans la table # donc, je précise les champs à afficher # Constitution d'un dictionnaire pour associer l'id du genre sélectionné avec un nom de variable valeur_id_horaire_selected_dictionnaire = { "value_id_horaire_selected": id_horaire_sel } strsql_horaire_afficher = """SELECT id_horaires, date_et_heure_horaires FROM t_horaires WHERE id_horaires= %(value_id_horaire_selected)s""" mc_afficher.execute( strsql_horaire_afficher, valeur_id_horaire_selected_dictionnaire) else: strsql_horaire_afficher = """SELECT id_horaires, date_et_heure_horaires FROM t_horaires ORDER BY id_horaires DESC""" mc_afficher.execute(strsql_horaire_afficher) data_horaire = mc_afficher.fetchall() print("data_horaire ", data_horaire, " Type : ", type(data_horaire)) except Exception as erreur: print(f"RGG Erreur générale.") # OM 2020.04.09 On dérive "Exception" par le "@obj_mon_application.errorhandler(404)" fichier "run_mon_app.py" # Ainsi on peut avoir un message d'erreur personnalisé. flash(f"RGG Exception {erreur}") raise Exception(f"RGG Erreur générale. {erreur}") raise MaBdErreurOperation( f"RGG Exception {msg_erreurs['ErreurNomBD']['message']} {erreur}" ) # Envoie la page "HTML" au serveur. return render_template("home.html", data=data_horaire)
def collaborateur_ajouter_wtf(): form = FormWTFAjouterCollaborateur() if request.method == "POST": try: try: # Renvoie une erreur si la connexion est perdue. MaBaseDeDonnee().connexion_bd.ping(False) except Exception as erreur: flash(f"Dans Gestion genres ...terrible erreur, il faut connecter une base de donnée", "danger") print(f"Exception grave Classe constructeur GestionGenres {erreur.args[0]}") raise MaBdErreurConnexion(f"{msg_erreurs['ErreurConnexionBD']['message']} {erreur.args[0]}") if form.validate_on_submit(): name_collaborateur_wtf = form.nom_famille_wtf.data prenom_collaborateur_wtf = form.prenom_wtf.data name_collaborateur = name_collaborateur_wtf.capitalize() prenom_collaborateur = prenom_collaborateur_wtf.capitalize() valeurs_insertion_dictionnaire = {"value_name": name_collaborateur, "value_firstName": prenom_collaborateur} print("valeurs_insertion_dictionnaire ", valeurs_insertion_dictionnaire) strsql_insert_genre = """INSERT INTO t_collaborateur (id_collaborateur,nom_famille,prenom,role) VALUES (NULL,%(value_name)s,%(value_firstName)s,0)""" with MaBaseDeDonnee() as mconn_bd: mconn_bd.mabd_execute(strsql_insert_genre, valeurs_insertion_dictionnaire) flash(f"Données insérées !!", "info") print(f"Données insérées !!") print(f"Données insérées !!") # Pour afficher et constater l'insertion de la valeur, on affiche en ordre inverse. (DESC) return redirect(url_for('collaborateur_afficher', order_by='DESC', id_collaborateur_sel=0)) # ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except pymysql.err.IntegrityError as erreur_genre_doublon: # Dérive "pymysql.err.IntegrityError" dans "MaBdErreurDoublon" fichier "erreurs/exceptions.py" # Ainsi on peut avoir un message d'erreur personnalisé. code, msg = erreur_genre_doublon.args flash(f"{error_codes.get(code, msg)} ", "warning") # OM 2020.04.16 ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except (pymysql.err.OperationalError, pymysql.ProgrammingError, pymysql.InternalError, TypeError) as erreur_gest_genr_crud: code, msg = erreur_gest_genr_crud.args flash(f"{error_codes.get(code, msg)} ", "danger") flash(f"Erreur dans Gestion genres CRUD : {sys.exc_info()[0]} " f"{erreur_gest_genr_crud.args[0]} , " f"{erreur_gest_genr_crud}", "danger") return render_template("collaborateur/collaborateur_ajouter_wtf.html", form=form)
def collaborateur_afficher(order_by, id_collaborateur_sel): if request.method == "GET": try: try: # Renvoie une erreur si la connexion est perdue. MaBaseDeDonnee().connexion_bd.ping(False) except Exception as erreur: flash(f"Dans Gestion genres ...terrible erreur, il faut connecter une base de donnée", "danger") print(f"Exception grave Classe constructeur GestionGenres {erreur.args[0]}") raise MaBdErreurConnexion(f"{msg_erreurs['ErreurConnexionBD']['message']} {erreur.args[0]}") with MaBaseDeDonnee().connexion_bd.cursor() as mc_afficher: if order_by == "ASC" and id_collaborateur_sel == 0: strsql_collaborateur_afficher = """SELECT id_collaborateur, nom_famille, prenom FROM t_collaborateur ORDER BY id_collaborateur ASC""" mc_afficher.execute(strsql_collaborateur_afficher) elif order_by == "ASC": # C'EST LA QUE VOUS ALLEZ DEVOIR PLACER VOTRE PROPRE LOGIQUE MySql # la commande MySql classique est "SELECT * FROM t_genre" # Pour "lever"(raise) une erreur s'il y a des erreurs sur les noms d'attributs dans la table # donc, je précise les champs à afficher # Constitution d'un dictionnaire pour associer l'id du genre sélectionné avec un nom de variable valeur_id_collaborateur_selected_dictionnaire = { "value_id_collaborateur_selected": id_collaborateur_sel} strsql_collaborateur_afficher = """SELECT id_collaborateur, nom_famille, prenom FROM t_collaborateur WHERE id_collaborateur= %(value_id_collaborateur_selected)s""" mc_afficher.execute(strsql_collaborateur_afficher, valeur_id_collaborateur_selected_dictionnaire) else: strsql_collaborateur_afficher = """SELECT id_collaborateur, nom_famille, prenom FROM t_collaborateur ORDER BY id_collaborateur DESC""" mc_afficher.execute(strsql_collaborateur_afficher) data_collaborateur = mc_afficher.fetchall() print("data_collaborateur ", data_collaborateur, " Type : ", type(data_collaborateur)) # Différencier les messages si la table est vide. if not data_collaborateur and id_collaborateur_sel == 0: flash("""La table "t_collaborateur" est vide. !!""", "warning") elif not data_collaborateur and id_collaborateur_sel > 0: # Si l'utilisateur change l'id_collaborateur dans l'URL et que le genre n'existe pas, flash(f"Le collaborateur demandé n'existe pas !!", "warning") else: # Dans tous les autres cas, c'est que la table "t_genre" est vide. # OM 2020.04.09 La ligne ci-dessous permet de donner un sentiment rassurant aux utilisateurs. flash(f"Données collaborateur affichés !!", "primary") except Exception as erreur: print(f"RGG Erreur générale.") # OM 2020.04.09 On dérive "Exception" par le "@obj_mon_application.errorhandler(404)" fichier "run_mon_app.py" # Ainsi on peut avoir un message d'erreur personnalisé. flash(f"RGG Exception {erreur}") raise Exception(f"RGG Erreur générale. {erreur}") raise MaBdErreurOperation(f"RGG Exception {msg_erreurs['ErreurNomBD']['message']} {erreur}") # Envoie la page "HTML" au serveur. return render_template("collaborateur/collaborateur_afficher.html", data=data_collaborateur)
def login(): obj_mon_application.logger.warning("login") # Message de sortie si quelque chose ne va pas ... msg = '' # Vérifiez si des requêtes POST "nom d'utilisateur" et "mot de passe" existent (formulaire soumis par l'utilisateur) if request.method == 'POST' and 'username' in request.form and 'password' in request.form: obj_mon_application.logger.warning("LOGIN 2") # Créez des variables pour un accès facile username = request.form['username'] password = request.form['password'] hs = hashlib.sha256(password.encode("utf-8")).hexdigest() # Vérifier si le compte existe en utilisant MySQL with MaBaseDeDonnee().connexion_bd.cursor() as cursor: cursor.execute('SELECT * FROM t_identification WHERE nom_utilisateur = %s AND mot_de_passe = %s', (username, hs,)) # Récupérer un enregistrement et renvoyer le résultat account = cursor.fetchone() # Si le compte existe dans la table des comptes dans la base de données externe if account: obj_mon_application.logger.warning('loggedin') # Créer des données de session, nous pouvons accéder à ces données dans d'autres itinéraires session['loggedin'] = True session['id_identification'] = account['id_identification'] session['nom_utilisateur'] = account['nom_utilisateur'] # Redirection à l'accueil return redirect(url_for('homepage', order_by='ASC', id_horaire_sel=1)) else: obj_mon_application.logger.warning('Not loggedin') # Le compte n'existe pas ou le nom d'utilisateur / mot de passe est incorrect msg = 'Incorrect username/password!' # Afficher le formulaire de connexion avec un message (le cas échéant) return render_template('index.html', msg=msg)
def genres_films_afficher_data(valeur_id_details_collaborateurs_selected_dict): print("valeur_id_details_collaborateurs_selected_dict...", valeur_id_details_collaborateurs_selected_dict) try: strsql_film_selected = """SELECT id_collaborateur, nom_famille, prenom, GROUP_CONCAT(id_details_collaborateur) as GenresFilms FROM t_collaborateur_details_collaborateur INNER JOIN t_collaborateur ON t_collaborateur.id_collaborateur = t_collaborateur_details_collaborateur.fk_collaborateur INNER JOIN t_details_collaborateur ON t_details_collaborateur.id_details_collaborateur = t_collaborateur_details_collaborateur.fk_details_collaborateur WHERE id_collaborateur = %(value_id_details_collaborateurs_selected)s""" strsql_genres_films_non_attribues = """SELECT id_details_collaborateur, sexe, rue, numero_rue, npa, ville, pays, telephone, date_entree_entreprise FROM t_details_collaborateur WHERE id_details_collaborateur not in(SELECT id_details_collaborateur as idGenresFilms FROM t_collaborateur_details_collaborateur INNER JOIN t_collaborateur ON t_collaborateur.id_collaborateur = t_collaborateur_details_collaborateur.fk_collaborateur INNER JOIN t_details_collaborateur ON t_details_collaborateur.id_details_collaborateur = t_collaborateur_details_collaborateur.fk_details_collaborateur WHERE id_collaborateur = %(value_id_details_collaborateurs_selected)s)""" strsql_genres_films_attribues = """SELECT id_collaborateur, id_details_collaborateur, sexe, rue, numero_rue, npa, ville, pays, telephone, date_entree_entreprise FROM t_collaborateur_details_collaborateur INNER JOIN t_collaborateur ON t_collaborateur.id_collaborateur = t_collaborateur_details_collaborateur.fk_collaborateur INNER JOIN t_details_collaborateur ON t_details_collaborateur.id_details_collaborateur = t_collaborateur_details_collaborateur.fk_details_collaborateur WHERE id_collaborateur = %(value_id_details_collaborateurs_selected)s""" # Du fait de l'utilisation des "context managers" on accède au curseur grâce au "with". with MaBaseDeDonnee().connexion_bd.cursor() as mc_afficher: # Envoi de la commande MySql mc_afficher.execute( strsql_genres_films_non_attribues, valeur_id_details_collaborateurs_selected_dict) # Récupère les données de la requête. data_genres_films_non_attribues = mc_afficher.fetchall() # Affichage dans la console print( "genres_films_afficher_data ----> data_genres_films_non_attribues ", data_genres_films_non_attribues, " Type : ", type(data_genres_films_non_attribues)) # Envoi de la commande MySql mc_afficher.execute( strsql_film_selected, valeur_id_details_collaborateurs_selected_dict) # Récupère les données de la requête. data_film_selected = mc_afficher.fetchall() # Affichage dans la console print("data_film_selected ", data_film_selected, " Type : ", type(data_film_selected)) # Envoi de la commande MySql mc_afficher.execute( strsql_genres_films_attribues, valeur_id_details_collaborateurs_selected_dict) # Récupère les données de la requête. data_genres_films_attribues = mc_afficher.fetchall() # Affichage dans la console print("data_genres_films_attribues ", data_genres_films_attribues, " Type : ", type(data_genres_films_attribues)) # Retourne les données des "SELECT" return data_film_selected, data_genres_films_non_attribues, data_genres_films_attribues except pymysql.Error as pymysql_erreur: code, msg = pymysql_erreur.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"pymysql.Error Erreur dans genres_films_afficher_data : {sys.exc_info()[0]} " f"{pymysql_erreur.args[0]} , " f"{pymysql_erreur}", "danger") except Exception as exception_erreur: code, msg = exception_erreur.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"Exception Erreur dans genres_films_afficher_data : {sys.exc_info()[0]} " f"{exception_erreur.args[0]} , " f"{exception_erreur}", "danger") except pymysql.err.IntegrityError as IntegrityError_genres_films_afficher_data: code, msg = IntegrityError_genres_films_afficher_data.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"pymysql.err.IntegrityError Erreur dans genres_films_afficher_data : {sys.exc_info()[0]} " f"{IntegrityError_genres_films_afficher_data.args[0]} , " f"{IntegrityError_genres_films_afficher_data}", "danger")
def details_collaborateurs_afficher(id_details_collaborateurs_sel): if request.method == "GET": try: try: # Renvoie une erreur si la connexion est perdue. MaBaseDeDonnee().connexion_bd.ping(False) except Exception as Exception_init_films_genres_afficher: code, msg = Exception_init_films_genres_afficher.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"Exception _init_films_genres_afficher problème de connexion BD : {sys.exc_info()[0]} " f"{Exception_init_films_genres_afficher.args[0]} , " f"{Exception_init_films_genres_afficher}", "danger") raise MaBdErreurConnexion( f"{msg_erreurs['ErreurConnexionBD']['message']} {erreur.args[0]}" ) with MaBaseDeDonnee().connexion_bd.cursor() as mc_afficher: strsql_genres_films_afficher_data = """SELECT id_collaborateur, nom_famille, prenom, GROUP_CONCAT(sexe,', ', rue,', ', numero_rue,', ', npa,', ', ville,', ', pays,', ', telephone,', ', date_entree_entreprise) as GenresFilms FROM t_collaborateur_details_collaborateur RIGHT JOIN t_collaborateur ON t_collaborateur.id_collaborateur = t_collaborateur_details_collaborateur.fk_collaborateur LEFT JOIN t_details_collaborateur ON t_details_collaborateur.id_details_collaborateur = t_collaborateur_details_collaborateur.fk_details_collaborateur GROUP BY id_collaborateur""" if id_details_collaborateurs_sel == 0: # le paramètre 0 permet d'afficher tous les films # Sinon le paramètre représente la valeur de l'id du film mc_afficher.execute(strsql_genres_films_afficher_data) else: # Constitution d'un dictionnaire pour associer l'id du film sélectionné avec un nom de variable valeur_id_details_collaborateurs_selected_dictionnaire = { "value_id_details_collaborateurs_selected": id_details_collaborateurs_sel } # En MySql l'instruction HAVING fonctionne comme un WHERE... mais doit être associée à un GROUP BY # L'opérateur += permet de concaténer une nouvelle valeur à la valeur de gauche préalablement définie. strsql_genres_films_afficher_data += """ HAVING id_film= %(value_id_details_collaborateurs_selected)s""" mc_afficher.execute( strsql_genres_films_afficher_data, valeur_id_details_collaborateurs_selected_dictionnaire) # Récupère les données de la requête. data_genres_films_afficher = mc_afficher.fetchall() print("data_genres ", data_genres_films_afficher, " Type : ", type(data_genres_films_afficher)) # Différencier les messages. if not data_genres_films_afficher and id_details_collaborateurs_sel == 0: flash("""La table "t_film" est vide. !""", "warning") elif not data_genres_films_afficher and id_details_collaborateurs_sel > 0: # Si l'utilisateur change l'id_film dans l'URL et qu'il ne correspond à aucun film flash( f"Le film {id_details_collaborateurs_sel} demandé n'existe pas !!", "warning") else: flash(f"Données colllaborateur et details affichés !!", "primary") except Exception as Exception_films_genres_afficher: code, msg = Exception_films_genres_afficher.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"Exception films_genres_afficher : {sys.exc_info()[0]} " f"{Exception_films_genres_afficher.args[0]} , " f"{Exception_films_genres_afficher}", "danger") # Envoie la page "HTML" au serveur. return render_template( "details_collaborateurs/details_collaborateurs_afficher.html", data=data_genres_films_afficher)
def update_genre_film_selected(): if request.method == "POST": try: # Récupère l'id du film sélectionné id_details_collaborateurs_selected = session[ 'session_id_film_genres_edit'] print("session['session_id_film_genres_edit'] ", session['session_id_film_genres_edit']) # Récupère la liste des genres qui ne sont pas associés au film sélectionné. old_lst_data_genres_films_non_attribues = session[ 'session_lst_data_genres_films_non_attribues'] print("old_lst_data_genres_films_non_attribues ", old_lst_data_genres_films_non_attribues) # Récupère la liste des genres qui sont associés au film sélectionné. old_lst_data_genres_films_attribues = session[ 'session_lst_data_genres_films_old_attribues'] print("old_lst_data_genres_films_old_attribues ", old_lst_data_genres_films_attribues) # Effacer toutes les variables de session. session.clear() # Récupère ce que l'utilisateur veut modifier comme genres dans le composant "tags-selector-tagselect" # dans le fichier "genres_films_modifier_tags_dropbox.html" new_lst_str_genres_films = request.form.getlist('name_select_tags') print("new_lst_str_genres_films ", new_lst_str_genres_films) # OM 2021.05.02 Exemple : Dans "name_select_tags" il y a ['4','65','2'] # On transforme en une liste de valeurs numériques. [4,65,2] new_lst_int_genre_film_old = list( map(int, new_lst_str_genres_films)) print("new_lst_genre_film ", new_lst_int_genre_film_old, "type new_lst_genre_film ", type(new_lst_int_genre_film_old)) # Pour apprécier la facilité de la vie en Python... "les ensembles en Python" # https://fr.wikibooks.org/wiki/Programmation_Python/Ensembles # OM 2021.05.02 Une liste de "id_genre" qui doivent être effacés de la table intermédiaire "t_genre_film". lst_diff_genres_delete_b = list( set(old_lst_data_genres_films_attribues) - set(new_lst_int_genre_film_old)) print("lst_diff_genres_delete_b ", lst_diff_genres_delete_b) # Une liste de "id_genre" qui doivent être ajoutés à la "t_genre_film" lst_diff_genres_insert_a = list( set(new_lst_int_genre_film_old) - set(old_lst_data_genres_films_attribues)) print("lst_diff_genres_insert_a ", lst_diff_genres_insert_a) # SQL pour insérer une nouvelle association entre # "fk_film"/"id_film" et "fk_genre"/"id_genre" dans la "t_genre_film" strsql_insert_genre_film = """INSERT INTO t_collaborateur_details_collaborateur (id_collaborateur_details_collaborateur, fk_details_collaborateur, fk_collaborateur) VALUES (NULL, %(value_fk_genre)s, %(value_fk_film)s)""" # SQL pour effacer une (des) association(s) existantes entre "id_film" et "id_genre" dans la "t_genre_film" strsql_delete_genre_film = """DELETE FROM t_collaborateur_details_collaborateur WHERE fk_details_collaborateur = %(value_fk_genre)s AND fk_collaborateur = %(value_fk_film)s""" with MaBaseDeDonnee() as mconn_bd: # Pour le film sélectionné, parcourir la liste des genres à INSÉRER dans la "t_genre_film". # Si la liste est vide, la boucle n'est pas parcourue. for id_genre_ins in lst_diff_genres_insert_a: # Constitution d'un dictionnaire pour associer l'id du film sélectionné avec un nom de variable # et "id_genre_ins" (l'id du genre dans la liste) associé à une variable. valeurs_film_sel_genre_sel_dictionnaire = { "value_fk_film": id_details_collaborateurs_selected, "value_fk_genre": id_genre_ins } mconn_bd.mabd_execute( strsql_insert_genre_film, valeurs_film_sel_genre_sel_dictionnaire) # Pour le film sélectionné, parcourir la liste des genres à EFFACER dans la "t_genre_film". # Si la liste est vide, la boucle n'est pas parcourue. for id_genre_del in lst_diff_genres_delete_b: # Constitution d'un dictionnaire pour associer l'id du film sélectionné avec un nom de variable # et "id_genre_del" (l'id du genre dans la liste) associé à une variable. valeurs_film_sel_genre_sel_dictionnaire = { "value_fk_film": id_details_collaborateurs_selected, "value_fk_genre": id_genre_del } # Du fait de l'utilisation des "context managers" on accède au curseur grâce au "with". # la subtilité consiste à avoir une méthode "mabd_execute" dans la classe "MaBaseDeDonnee" # ainsi quand elle aura terminé l'insertion des données le destructeur de la classe "MaBaseDeDonnee" # sera interprété, ainsi on fera automatiquement un commit mconn_bd.mabd_execute( strsql_delete_genre_film, valeurs_film_sel_genre_sel_dictionnaire) except Exception as Exception_update_genre_film_selected: code, msg = Exception_update_genre_film_selected.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"Exception update_genre_film_selected : {sys.exc_info()[0]} " f"{Exception_update_genre_film_selected.args[0]} , " f"{Exception_update_genre_film_selected}", "danger") # Après cette mise à jour de la table intermédiaire "t_genre_film", # on affiche les films et le(urs) genre(s) associé(s). return redirect( url_for( 'details_collaborateurs_afficher', id_details_collaborateurs_sel=id_details_collaborateurs_selected))
def edit_genre_film_selected(): if request.method == "GET": try: with MaBaseDeDonnee().connexion_bd.cursor() as mc_afficher: strsql_genres_afficher = """SELECT id_details_collaborateur, sexe, rue, numero_rue, npa, ville, pays, telephone, date_entree_entreprise FROM t_details_collaborateur ORDER BY id_details_collaborateur ASC""" mc_afficher.execute(strsql_genres_afficher) data_genres_all = mc_afficher.fetchall() print("dans edit_genre_film_selected ---> data_genres_all", data_genres_all) # Récupère la valeur de "id_film" du formulaire html "details_collaborateurs_afficher.html" # l'utilisateur clique sur le bouton "Modifier" et on récupère la valeur de "id_film" # grâce à la variable "id_film_genres_edit_html" dans le fichier "details_collaborateurs_afficher.html" # href="{{ url_for('edit_genre_film_selected', id_film_genres_edit_html=row.id_film) }}" id_film_genres_edit = request.values['id_film_genres_edit_html'] # Mémorise l'id du film dans une variable de session # (ici la sécurité de l'application n'est pas engagée) # il faut éviter de stocker des données sensibles dans des variables de sessions. session['session_id_film_genres_edit'] = id_film_genres_edit # Constitution d'un dictionnaire pour associer l'id du film sélectionné avec un nom de variable valeur_id_details_collaborateurs_selected_dictionnaire = { "value_id_details_collaborateurs_selected": id_film_genres_edit } # Récupère les données grâce à 3 requêtes MySql définie dans la fonction genres_films_afficher_data # 1) Sélection du film choisi # 2) Sélection des genres "déjà" attribués pour le film. # 3) Sélection des genres "pas encore" attribués pour le film choisi. # ATTENTION à l'ordre d'assignation des variables retournées par la fonction "genres_films_afficher_data" data_genre_film_selected, data_genres_films_non_attribues, data_genres_films_attribues = \ genres_films_afficher_data(valeur_id_details_collaborateurs_selected_dictionnaire) print(data_genre_film_selected) lst_data_film_selected = [ item['id_collaborateur'] for item in data_genre_film_selected ] print("lst_data_film_selected ", lst_data_film_selected, type(lst_data_film_selected)) # Dans le composant "tags-selector-tagselect" on doit connaître # les genres qui ne sont pas encore sélectionnés. lst_data_genres_films_non_attribues = [ item['id_details_collaborateur'] for item in data_genres_films_non_attribues ] session[ 'session_lst_data_genres_films_non_attribues'] = lst_data_genres_films_non_attribues print("lst_data_genres_films_non_attribues ", lst_data_genres_films_non_attribues, type(lst_data_genres_films_non_attribues)) # Dans le composant "tags-selector-tagselect" on doit connaître # les genres qui sont déjà sélectionnés. lst_data_genres_films_old_attribues = [ item['id_details_collaborateur'] for item in data_genres_films_attribues ] session[ 'session_lst_data_genres_films_old_attribues'] = lst_data_genres_films_old_attribues print("lst_data_genres_films_old_attribues ", lst_data_genres_films_old_attribues, type(lst_data_genres_films_old_attribues)) print(" data data_genre_film_selected", data_genre_film_selected, "type ", type(data_genre_film_selected)) print(" data data_genres_films_non_attribues ", data_genres_films_non_attribues, "type ", type(data_genres_films_non_attribues)) print(" data_genres_films_attribues ", data_genres_films_attribues, "type ", type(data_genres_films_attribues)) # Extrait les valeurs contenues dans la table "t_genres", colonne "intitule_genre" # Le composant javascript "tagify" pour afficher les tags n'a pas besoin de l'id_genre lst_data_genres_films_non_attribues = [ item['sexe'] for item in data_genres_films_non_attribues ] print("lst_all_genres gf_edit_genre_film_selected ", lst_data_genres_films_non_attribues, type(lst_data_genres_films_non_attribues)) except Exception as Exception_edit_genre_film_selected: code, msg = Exception_edit_genre_film_selected.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"Exception edit_genre_film_selected : {sys.exc_info()[0]} " f"{Exception_edit_genre_film_selected.args[0]} , " f"{Exception_edit_genre_film_selected}", "danger") return render_template( "details_collaborateurs/details_collaborateurs_modifier_tags_dropbox.html", data_genres=data_genres_all, data_film_selected=data_genre_film_selected, data_genres_attribues=data_genres_films_attribues, data_genres_non_attribues=data_genres_films_non_attribues)
def details_collaborateur_ajouter_wtf(): form = FormWTFAjouterDetails() if request.method == "POST": try: try: # Renvoie une erreur si la connexion est perdue. MaBaseDeDonnee().connexion_bd.ping(False) except Exception as erreur: flash( f"Dans Gestion genres ...terrible erreur, il faut connecter une base de donnée", "danger") print( f"Exception grave Classe constructeur GestionGenres {erreur.args[0]}" ) raise MaBdErreurConnexion( f"{msg_erreurs['ErreurConnexionBD']['message']} {erreur.args[0]}" ) if form.validate_on_submit(): sexe_collaborateur_wtf = form.sexe_wtf.data sexe_collaborateur = sexe_collaborateur_wtf.capitalize() rue_collaborateur_wtf = form.rue_wtf.data rue_collaborateur = rue_collaborateur_wtf.capitalize() numero_rue_collaborateur_wtf = form.numero_rue_wtf.data numero_rue_collaborateur = numero_rue_collaborateur_wtf.capitalize( ) npa_collaborateur_wtf = form.npa_wtf.data npa_collaborateur = npa_collaborateur_wtf.capitalize() ville_collaborateur_wtf = form.ville_wtf.data ville_collaborateur = ville_collaborateur_wtf.capitalize() pays_collaborateur_wtf = form.pays_wtf.data pays_collaborateur = pays_collaborateur_wtf.capitalize() telephone_collaborateur_wtf = form.telephone_wtf.data telephone_collaborateur = telephone_collaborateur_wtf.capitalize( ) date_entree_entreprise_collaborateur_wtf = form.date_entree_entreprise_wtf.data date_entree_entreprise_collaborateur = date_entree_entreprise_collaborateur_wtf.capitalize( ) valeurs_insertion_dictionnaire = { "value_sexe": sexe_collaborateur, "value_rue": rue_collaborateur, "value_numero_rue": numero_rue_collaborateur, "value_npa": npa_collaborateur, "value_ville": ville_collaborateur, "value_pays": pays_collaborateur, "value_telephone": telephone_collaborateur, "value_date_entree": date_entree_entreprise_collaborateur } print("valeurs_insertion_dictionnaire ", valeurs_insertion_dictionnaire) strsql_insert_genre = """INSERT INTO t_details_collaborateur (id_details_collaborateur,sexe,rue,numero_rue,npa,ville,pays,telephone,date_entree_entreprise) VALUES (NULL,%(value_sexe)s,%(value_rue)s,%(value_numero_rue)s,%(value_npa)s,%(value_ville)s,%(value_pays)s,%(value_telephone)s,%(value_date_entree)s)""" with MaBaseDeDonnee() as mconn_bd: mconn_bd.mabd_execute(strsql_insert_genre, valeurs_insertion_dictionnaire) flash(f"Données insérées !!", "info") print(f"Données insérées !!") print(f"Données insérées !!") # Pour afficher et constater l'insertion de la valeur, on affiche en ordre inverse. (DESC) return redirect( url_for('details_collaborateurs_afficher', order_by='ASC', id_details_collaborateurs_sel=0)) # ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except pymysql.err.IntegrityError as erreur_genre_doublon: # Dérive "pymysql.err.IntegrityError" dans "MaBdErreurDoublon" fichier "erreurs/exceptions.py" # Ainsi on peut avoir un message d'erreur personnalisé. code, msg = erreur_genre_doublon.args flash(f"{error_codes.get(code, msg)} ", "warning") # OM 2020.04.16 ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except (pymysql.err.OperationalError, pymysql.ProgrammingError, pymysql.InternalError, TypeError) as erreur_gest_genr_crud: code, msg = erreur_gest_genr_crud.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"Erreur dans Gestion genres CRUD : {sys.exc_info()[0]} " f"{erreur_gest_genr_crud.args[0]} , " f"{erreur_gest_genr_crud}", "danger") return render_template( "Details_collaborateurs/details_collaborateur_ajouter.html", form=form)
def identification_delete_wtf(): data_films_attribue_genre_delete = None btn_submit_del = None # L'utilisateur vient de cliquer sur le bouton "DELETE". Récupère la valeur de "id_genre" id_identification_delete = request.values[ 'id_identification_btn_delete_html'] # Objet formulaire pour effacer le genre sélectionné. form_delete = FromWTFDeleteIdentification() try: print(" on submit ", form_delete.validate_on_submit()) if request.method == "POST" and form_delete.validate_on_submit(): if form_delete.submit_btn_annuler.data: return redirect( url_for("identification_afficher", order_by="ASC", id_identification_sel=0)) if form_delete.submit_btn_conf_del.data: # Récupère les données afin d'afficher à nouveau # le formulaire "genres/genre_delete_wtf.html" lorsque le bouton "Etes-vous sur d'effacer ?" est cliqué. data_films_attribue_genre_delete = session[ 'data_films_attribue_genre_delete'] print("data_films_attribue_genre_delete ", data_films_attribue_genre_delete) flash( f"Effacer les identifications de façon définitive de la BD !!!", "danger") # L'utilisateur vient de cliquer sur le bouton de confirmation pour effacer... # On affiche le bouton "Effacer genre" qui va irrémédiablement EFFACER le genre btn_submit_del = True if form_delete.submit_btn_del.data: valeur_delete_dictionnaire = { "value_id_identification": id_identification_delete } print("valeur_delete_dictionnaire ", valeur_delete_dictionnaire) str_sql_delete_films_genre = """DELETE FROM t_collaborateur_identification WHERE FK_collaborateur = %(value_id_identification)s""" str_sql_delete_idgenre = """DELETE FROM t_identification WHERE id_identification = %(value_id_identification)s""" # Manière brutale d'effacer d'abord la "FK_collaborateur", même si elle n'existe pas dans la "t_collaborateur_details_collaborateur" # Ensuite on peut effacer le genre vu qu'il n'est plus "lié" (INNODB) dans la "t_collaborateur_details_collaborateur" with MaBaseDeDonnee() as mconn_bd: mconn_bd.mabd_execute(str_sql_delete_films_genre, valeur_delete_dictionnaire) mconn_bd.mabd_execute(str_sql_delete_idgenre, valeur_delete_dictionnaire) flash(f"Identification définitivement effacé !!", "info") print(f"Identification définitivement effacé !!") # afficher les données return redirect( url_for('identification_afficher', order_by="ASC", id_identification_sel=0)) if request.method == "GET": valeur_select_dictionnaire = { "value_id_identification": id_identification_delete } print(id_identification_delete, type(id_identification_delete)) # Requête qui affiche tous les films qui ont le genre que l'utilisateur veut effacer str_sql_identification_delete = """SELECT id_collaborateur_identification, date_et_heure_arrivee, date_et_heure_depart FROM t_collaborateur_identification INNER JOIN t_identification ON t_collaborateur_identification.FK_identification = t_identification.id_identification INNER JOIN t_collaborateur ON t_collaborateur_identification.FK_collaborateur = t_collaborateur.id_collaborateur WHERE FK_collaborateur = %(value_id_identification)s""" mybd_curseur = MaBaseDeDonnee().connexion_bd.cursor() mybd_curseur.execute(str_sql_identification_delete, valeur_select_dictionnaire) data_films_attribue_genre_delete = mybd_curseur.fetchall() print("data_films_attribue_genre_delete...", data_films_attribue_genre_delete) # Nécessaire pour mémoriser les données afin d'afficher à nouveau # le formulaire "genres/genre_delete_wtf.html" lorsque le bouton "Etes-vous sur d'effacer ?" est cliqué. session[ 'data_films_attribue_genre_delete'] = data_films_attribue_genre_delete # Opération sur la BD pour récupérer "id_genre" et "nom_famille" de la "t_genre" str_sql_id_identification = "SELECT id_identification, nom_utilisateur, courriel FROM t_identification WHERE id_identification = %(value_id_identification)s" mybd_curseur.execute(str_sql_id_identification, valeur_select_dictionnaire) # Une seule valeur est suffisante "fetchone()", # vu qu'il n'y a qu'un seul champ "nom genre" pour l'action DELETE data_nom_utilisateur_identification = mybd_curseur.fetchone() print("data_nom_utilisateur_identification ", data_nom_utilisateur_identification, " type ", type(data_nom_utilisateur_identification), " genre ", data_nom_utilisateur_identification["nom_utilisateur"]) # Afficher la valeur sélectionnée dans le champ du formulaire "genre_delete_wtf.html" form_delete.nom_utilisateur_identification_delete_wtf.data = data_nom_utilisateur_identification[ "nom_utilisateur"] form_delete.courriel_identification_delete_wtf.data = data_nom_utilisateur_identification[ "courriel"] # Le bouton pour l'action "DELETE" dans le form. "genre_delete_wtf.html" est caché. btn_submit_del = False # OM 2020.04.16 ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except KeyError: flash( f"__KeyError dans identification_delete_wtf : {sys.exc_info()[0]} {sys.exc_info()[1]} {sys.exc_info()[2]}", "danger") except ValueError: flash( f"Erreur dans identification_delete_wtf : {sys.exc_info()[0]} {sys.exc_info()[1]}", "danger") except (pymysql.err.OperationalError, pymysql.ProgrammingError, pymysql.InternalError, pymysql.err.IntegrityError, TypeError) as erreur_gest_genr_crud: code, msg = erreur_gest_genr_crud.args flash( f"attention : {error_codes.get(code, msg)} {erreur_gest_genr_crud} ", "danger") flash( f"Erreur dans identification_delete_wtf : {sys.exc_info()[0]} " f"{erreur_gest_genr_crud.args[0]} , " f"{erreur_gest_genr_crud}", "danger") flash( f"__KeyError dans identification_delete_wtf : {sys.exc_info()[0]} {sys.exc_info()[1]} {sys.exc_info()[2]}", "danger") return render_template( "identification/identification_delete_wtf.html", form_delete=form_delete, btn_submit_del=btn_submit_del, data_identification_associes=data_films_attribue_genre_delete)
def identification_update_wtf(): # L'utilisateur vient de cliquer sur le bouton "EDIT". Récupère la valeur de "id_genre" id_identification_update = request.values[ 'id_identification_btn_edit_html'] # Objet formulaire pour l'UPDATE form_update = FormWTFUpdateIdentification() try: print(" on submit ", form_update.validate_on_submit()) if form_update.validate_on_submit(): # Récupèrer la valeur du champ depuis "genre_update_wtf.html" après avoir cliqué sur "SUBMIT". # Puis la convertir en lettres minuscules. nom_utilisateur_identification_update = form_update.nom_utilisateur_identification_update_wtf.data nom_utilisateur_identification_update = nom_utilisateur_identification_update.capitalize( ) courriel_identification_update = form_update.courriel_identification_update_wtf.data courriel_identification_update = courriel_identification_update.lower( ) valeur_update_dictionnaire = { "value_id_identification": id_identification_update, "value_nom_utilisateur_identification": nom_utilisateur_identification_update, "value_courriel_identification": courriel_identification_update } print("valeur_update_dictionnaire ", valeur_update_dictionnaire) str_sql_update_nom_utilisateur = """UPDATE t_identification SET nom_utilisateur = %(value_nom_utilisateur_identification)s, courriel = %(value_courriel_identification)s WHERE id_identification = %(value_id_identification)s""" with MaBaseDeDonnee() as mconn_bd: mconn_bd.mabd_execute(str_sql_update_nom_utilisateur, valeur_update_dictionnaire) flash(f"Donnée mise à jour !!", "info") print(f"Donnée mise à jour !!") # afficher et constater que la donnée est mise à jour. # Affiche seulement la valeur modifiée, "ASC" et l'"id_collaborateur_update" return redirect( url_for('identification_afficher', order_by="ASC", id_identification_sel=id_identification_update)) elif request.method == "GET": # Opération sur la BD pour récupérer "id_genre" et "nom_famille" de la "t_genre" str_sql_id_identification = "SELECT id_identification, nom_utilisateur, courriel FROM t_identification WHERE id_identification = %(value_id_identification)s" valeur_select_dictionnaire = { "value_id_identification": id_identification_update } mybd_curseur = MaBaseDeDonnee().connexion_bd.cursor() mybd_curseur.execute(str_sql_id_identification, valeur_select_dictionnaire) # Une seule valeur est suffisante "fetchone()", vu qu'il n'y a qu'un seul champ "nom genre" pour l'UPDATE data_nom_utilisateur_identification_collaborateur = mybd_curseur.fetchone( ) print( " ", data_nom_utilisateur_identification_collaborateur, " type ", type(data_nom_utilisateur_identification_collaborateur), " nom_utilisateur ", data_nom_utilisateur_identification_collaborateur["courriel"]) # Afficher la valeur sélectionnée dans le champ du formulaire "genre_update_wtf.html" form_update.nom_utilisateur_identification_update_wtf.data = data_nom_utilisateur_identification_collaborateur[ "nom_utilisateur"] form_update.courriel_identification_update_wtf.data = data_nom_utilisateur_identification_collaborateur[ "courriel"] # OM 2020.04.16 ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except KeyError: flash( f"__KeyError dans genre_update_wtf : {sys.exc_info()[0]} {sys.exc_info()[1]} {sys.exc_info()[2]}", "danger") except ValueError: flash( f"Erreur dans genre_update_wtf : {sys.exc_info()[0]} {sys.exc_info()[1]}", "danger") except (pymysql.err.OperationalError, pymysql.ProgrammingError, pymysql.InternalError, pymysql.err.IntegrityError, TypeError) as erreur_gest_genr_crud: code, msg = erreur_gest_genr_crud.args flash( f"attention : {error_codes.get(code, msg)} {erreur_gest_genr_crud} ", "danger") flash( f"Erreur dans genre_update_wtf : {sys.exc_info()[0]} " f"{erreur_gest_genr_crud.args[0]} , " f"{erreur_gest_genr_crud}", "danger") flash( f"__KeyError dans genre_update_wtf : {sys.exc_info()[0]} {sys.exc_info()[1]} {sys.exc_info()[2]}", "danger") return render_template("identification/identification_update_wtf.html", form_update=form_update)
def identification_ajouter_wtf(): form = FormWTFAjouterCollaborateur() if request.method == "POST": try: try: # Renvoie une erreur si la connexion est perdue. MaBaseDeDonnee().connexion_bd.ping(False) except Exception as erreur: flash( f"Dans Gestion des identification ...terrible erreur, il faut connecter une base de donnée", "danger") print( f"Exception grave Classe constructeur GestionGenres {erreur.args[0]}" ) raise MaBdErreurConnexion( f"{msg_erreurs['ErreurConnexionBD']['message']} {erreur.args[0]}" ) if form.validate_on_submit(): nom_utilisateur_identification_wtf = form.nom_utilisateur_wtf.data mot_de_passe_identification_wtf = form.mot_de_passe_wtf.data courriel_identificaiton_wtf = form.courriel_wtf.data nom_utilisateur_identification = nom_utilisateur_identification_wtf.capitalize( ) mot_de_passe_identification = mot_de_passe_identification_wtf.lower( ) courriel_identificaiton = courriel_identificaiton_wtf.lower() valeurs_insertion_dictionnaire = { "value_nom_utilisateur": nom_utilisateur_identification, "value_courriel": courriel_identificaiton, "value_mot_de_passe": mot_de_passe_identification } # ligne pour hasher le mdp # hs = hashlib.sha256(password.encode("utf-8")).hexdigest() print("valeurs_insertion_dictionnaire ", valeurs_insertion_dictionnaire) strsql_insert_genre = """INSERT INTO t_identification (id_identification,nom_utilisateur,mot_de_passe,courriel) VALUES (NULL,%(value_nom_utilisateur)s,%(value_mot_de_passe)s,%(value_courriel)s)""" with MaBaseDeDonnee() as mconn_bd: mconn_bd.mabd_execute(strsql_insert_genre, valeurs_insertion_dictionnaire) flash(f"Données insérées !!", "info") print(f"Données insérées !!") print(f"Données insérées !!") # Pour afficher et constater l'insertion de la valeur, on affiche en ordre inverse. (DESC) return redirect( url_for('identification_afficher', order_by='DESC', id_identification_sel=0)) # ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except pymysql.err.IntegrityError as erreur_genre_doublon: # Dérive "pymysql.err.IntegrityError" dans "MaBdErreurDoublon" fichier "erreurs/exceptions.py" # Ainsi on peut avoir un message d'erreur personnalisé. code, msg = erreur_genre_doublon.args flash(f"{error_codes.get(code, msg)} ", "warning") # OM 2020.04.16 ATTENTION à l'ordre des excepts, il est très important de respecter l'ordre. except (pymysql.err.OperationalError, pymysql.ProgrammingError, pymysql.InternalError, TypeError) as erreur_gest_genr_crud: code, msg = erreur_gest_genr_crud.args flash(f"{error_codes.get(code, msg)} ", "danger") flash( f"Erreur dans Gestion genres CRUD : {sys.exc_info()[0]} " f"{erreur_gest_genr_crud.args[0]} , " f"{erreur_gest_genr_crud}", "danger") return render_template("identification/identifiaction_ajouter_wtf.html", form=form)