from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed from wtforms import StringField, SubmitField, FileField, RadioField, widgets, FieldList, FormField, HiddenField from wtforms.validators import DataRequired, Optional from wtforms_alchemy import model_form_factory, ClassMap from wtforms_alchemy.fields import QuerySelectMultipleField from app import db import app.models as models import yaml import json import os import re REPERTOIRE_EXPORT = "./export/" if not os.path.exists(REPERTOIRE_EXPORT): os.makedirs(REPERTOIRE_EXPORT) categorie_liste = ["saes","ressources","acs","ues","semestres","competences"] categorie_to_model = {"saes": "SAE", "ressources": "Ressource", "acs": "AC", "coefsaes": "CoefSAE", "coefressources": "CoefRessource", "pns": "PN", "semestres": "Semestre", "competences": "Competence"} separateur = None BaseModelForm = model_form_factory(FlaskForm, include_primary_keys=True) class CustomEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, models.Semestre): return obj.num if isinstance(obj, models.Competence) or isinstance(obj, models.SAE) or isinstance(obj, models.Ressource) or isinstance(obj, models.AC): return obj.code return json.JSONEncoder.default(self, obj) class ModelForm(BaseModelForm): @classmethod def get_session(self): return db.session class RefListField(QuerySelectMultipleField): option_widget=widgets.CheckboxInput() class AccueilForm(FlaskForm): ajouter = SubmitField("Ajouter") reset = SubmitField("Reset") exporterJSON = SubmitField("ExporterJSON") exporterYAML = SubmitField("ExporterYAML") fichier = FileField("Choisir fichier", validators=[FileAllowed(["yml","json"], "Fichier YAML/JSON seulement!")]) importer = SubmitField("Importer") def ListRef(self): result = {"semestres": [], "competences": [], "acs": [], "pns": [], "saes": [], "coefsaes": [], "ressources": [], "coefressources": []} associations = {"semestres_competences": models.Semestres_Competences, "acs_competences": models.ACs_Competences, "ressources_acs": models.Ressources_ACs, "ressources_saes": models.Ressources_SAEs, "saes_acs": models.SAEs_ACs} for key in result.keys(): model = getattr(models, categorie_to_model[key]) for ref in model.query.all(): result[key].append(ref.export()) for assoName, association in associations.items(): result[assoName] = db.session.query(association).all() return result def exportJSON(self): result = self.ListRef() fichier = REPERTOIRE_EXPORT + "referentiels" + ".json" with open(fichier, "w", encoding="utf8") as fid: json.dump(result, fid, cls=CustomEncoder, indent=4) def exportYAML(self): result = self.ListRef() fichier = REPERTOIRE_EXPORT + "referentiels" + ".yml" with open(fichier, "w", encoding="utf8") as fid: yaml.dump(yaml.safe_load(json.dumps(result, cls=CustomEncoder)), fid, indent=4, sort_keys=False) def importRef(self): fichier = self.fichier.data filename, extension = fichier.filename.split(".") if extension == "yml": filedata = yaml.safe_load(fichier.read()) elif extension == "json": filedata = json.load(fichier) else: self.fichier.errors.append("Une erreur a été produite.") return for categorie, liste in filedata.items(): if "_" not in categorie: model = getattr(models, categorie_to_model[categorie]) for ref in liste: print("Adding:", ref) if categorie == "semestres": semestre = model.query.filter_by(num=ref["num"]).first() if not semestre: ref["ues"] = [] db.session.add(model(**ref)) else: print("Not added: Already in database") elif "coef" in categorie: competence = models.Competence.query.filter_by(code=ref["competence"]).first() if categorie == "coefsaes": sae = models.SAE.query.filter_by(code=ref["sae"]).first() if not models.CoefSAE.query.filter_by(sae=sae,competence=competence).first(): db.session.add(models.CoefSAE(sae=sae,competence=competence,coef=ref["coef"])) else: print("Not added: Already in database") elif categorie == "coefressources": ressource = models.Ressource.query.filter_by(code=ref["ressource"]).first() if not models.CoefRessource.query.filter_by(ressource=ressource, competence=competence).first(): db.session.add(models.CoefRessource(ressource=ressource, competence=competence,coef=ref["coef"])) else: print("Not added: Already in database") else: refBDD = model.query.filter_by(code=ref["code"]).first() if not refBDD: for categorieRef, valeur in ref.items(): if categorieRef in categorie_liste: ref[categorieRef] = [] db.session.add(model(**ref)) else: print("Not added: Already in database") else: for assoc in liste: print("Adding association:", assoc) firstModelname, secondModelname = categorie.split("_") firstVal, secondVal = assoc firstModel = getattr(models, categorie_to_model[firstModelname]) secondModel = getattr(models, categorie_to_model[secondModelname]) if firstModelname == "semestres": firstRef = firstModel.query.filter_by(num=firstVal).first() secondRef = secondModel.query.filter_by(code=secondVal).first() if secondRef not in firstRef.ues: firstRef.ues.append(secondRef) else: print("Not added: Association already exist") else: firstRef = firstModel.query.filter_by(code=firstVal).first() secondRef = secondModel.query.filter_by(code=secondVal).first() if secondRef not in firstRef.__dict__[secondModelname]: firstRef.__dict__[secondModelname].append(secondRef) else: print("Not added: Association already exist") db.session.commit() class CoefForm(FlaskForm): objetformation = HiddenField("Objet de formation") coef = StringField("Coef") class UEForm(FlaskForm): ue = HiddenField("Competence") acs = RefListField("Liste des ACs", query_factory=lambda: models.AC.query.all(), get_label=lambda ref: ref.getLabel()) ressources = RefListField("Liste des Ressources inclus dans les ACs", query_factory=lambda: [], get_label=lambda ref: ref.getLabel()) saes = RefListField("Liste des SAEs inclus dans les ACs", query_factory=lambda: [], get_label=lambda ref: ref.getLabel()) coef = FieldList(FormField(CoefForm)) class SemestreForm(FlaskForm): ues = RefListField("Liste des UEs", query_factory=lambda: models.Competence.query.all(), get_label=lambda ref: ref.getLabel()) ueform = FieldList(FormField(UEForm)) update = SubmitField("Update") class Form(ModelForm): class Meta: not_null_validator_type_map = ClassMap({db.String: [DataRequired()]}) sauvegarder = SubmitField("Sauvegarder") charger = SubmitField("Charger") supprimer = SubmitField("Supprimer") exporter = SubmitField("Exporter") fichier = FileField("Choisir fichier", validators=[FileAllowed(["yml"], "Fichier Yaml seulement!")]) importer = SubmitField("Importer") referentiel = RadioField("Liste des référentiels", validators=[Optional()]) def chargerRef(self): if self.referentiel.data == None: self.referentiel.errors.append("Aucun référentiel n'a été selectionné!") return False else: return True def chargerBDD(self, referentiel): for categorie in list(self.data.keys())[7:-1]: self[categorie].process_data(referentiel.__dict__[categorie]) self.referentiel.process_data(referentiel) def importerRef(self): if len(self.fichier.errors) == 0: if self.fichier.data.filename == "": self.fichier.errors.append("Aucun fichier selectioné.") return if re.match(self.regex, self.fichier.data.filename[:-4]) == None: self.fichier.errors.append("Mauvais type de référentiel!") return fichier_Yaml = yaml.safe_load(self.fichier.data.read()) for categorie, valeur in fichier_Yaml.items(): if categorie in categorie_liste: model = getattr(models, categorie_to_model[categorie]) self[categorie].process_data([model.query.filter_by(code=ref).first() for ref in valeur]) else: self[categorie].process_data(valeur) self.validate() def exporterRef(self): """ Exporte dans un fichier yaml les informations du formulaire rempli """ output = {} for categorie, valeur in list(self.data.items())[7:-1]: if categorie in categorie_liste: output[categorie] = [ referentiel.code for referentiel in valeur ] else: output[categorie] = valeur fichier = REPERTOIRE_EXPORT + self.code.data + ".yml" with open(fichier, "w", encoding="utf8") as fid: fid.write(yaml.dump(output)) def supprimerRef(self): if self.referentiel.data == None: self.referentiel.erros.append("Aucun référentiel n'a été selectionné!") return False else: temp = self.referentiel.data[1:-1].split() model = getattr(models, temp[0]) referentiel = model.query.filter_by(code=temp[1]).first() db.session.delete(referentiel) db.session.commit() return True def sauvegarderRef(self): model = getattr(models, self.__class__.__name__[:-4]) referentiel = model.query.filter_by(code=self.code.data).first() if referentiel == None: referentiel = model() self.populate_obj(referentiel) db.session.add(referentiel) db.session.commit() class PNForm(Form): regex = "^PN\d$" class Meta: model = models.PN type = RadioField("Type de parcours", choices=["1","2","3"]) class ACForm(Form): regex = "^AC\d{4}$" class Meta: model = models.AC saes = RefListField("Liste des SAEs", query_factory=lambda: models.SAE.query.all(), get_label=lambda ref: ref.getLabel()) ressources = RefListField("Liste des Ressources", query_factory=lambda: models.Ressource.query.all(), get_label=lambda ref: ref.getLabel()) class SAEForm(Form): regex = "^SAE\d{2}$" class Meta: model = models.SAE acs = RefListField("Liste des ACs", query_factory=lambda: models.AC.query.all(), get_label=lambda ref: ref.getLabel()) ressources = RefListField("Liste des Ressources", query_factory=lambda: models.Ressource.query.all(), get_label=lambda ref: ref.getLabel()) class RessourceForm(Form): regex = "^R\d{3}$" class Meta: model = models.Ressource acs = RefListField("Liste des ACs", query_factory=lambda: models.AC.query.all(), get_label=lambda ref: ref.getLabel()) saes = RefListField("Liste des SAEs", query_factory=lambda: models.SAE.query.all(), get_label=lambda ref: ref.getLabel()) class CompetenceForm(Form): regex = "^RT\d$" class Meta: model = models.Competence