diff --git a/app/models/but_refcomp.py b/app/models/but_refcomp.py index d595cd715b..e9d046e285 100644 --- a/app/models/but_refcomp.py +++ b/app/models/but_refcomp.py @@ -399,6 +399,12 @@ class ApcNiveau(db.Model, XMLModel): """Vrai si ce niveau fait partie du Tronc Commun""" return len(self.parcours) == self.competence.referentiel.parcours.count() + # Le ref. comp. ne change jamais (pas d'édition dans ScoDoc) + # on cache les résultats: + _niveaux_annee_de_parcours_cache: dict[ + tuple[int, int, int, int], list["ApcNiveau"] + ] = {} + @classmethod def niveaux_annee_de_parcours( cls, @@ -412,6 +418,15 @@ class ApcNiveau(db.Model, XMLModel): (dans ce cas, spécifier referentiel_competence) Si competence est indiquée, filtre les niveaux de cette compétence. """ + key = ( + parcour.id if parcour else None, + annee, + referentiel_competence.id if referentiel_competence else None, + competence.id if competence else None, + ) + result = cls._niveaux_annee_de_parcours_cache.get(key) + if result: + return result if annee not in {1, 2, 3}: raise ValueError("annee invalide pour un parcours BUT") referentiel_competence = ( @@ -428,10 +443,13 @@ class ApcNiveau(db.Model, XMLModel): ) if competence is not None: query = query.filter(ApcCompetence.id == competence.id) - return query.all() + result = query.all() + cls._niveaux_annee_de_parcours_cache[key] = result + return result annee_parcour: ApcAnneeParcours = parcour.annees.filter_by(ordre=annee).first() if not annee_parcour: + cls._niveaux_annee_de_parcours_cache[key] = [] return [] if competence is None: @@ -446,6 +464,7 @@ class ApcNiveau(db.Model, XMLModel): niveaux: list[ApcNiveau] = competence.niveaux.filter_by( annee=f"BUT{int(annee)}" ).all() + cls._niveaux_annee_de_parcours_cache[key] = niveaux return niveaux diff --git a/app/models/ues.py b/app/models/ues.py index 383f20f8fe..1daf127353 100644 --- a/app/models/ues.py +++ b/app/models/ues.py @@ -1,6 +1,7 @@ """ScoDoc 9 models : Unités d'Enseignement (UE) """ +from flask import g import pandas as pd from app import db, log @@ -8,7 +9,6 @@ from app.models import APO_CODE_STR_LEN from app.models import SHORT_STR_LEN from app.models.but_refcomp import ApcNiveau, ApcParcours from app.models.modules import Module -from app.scodoc.sco_exceptions import ScoFormationConflict from app.scodoc import sco_utils as scu @@ -107,6 +107,17 @@ class UniteEns(db.Model): If convert_objects, convert all attributes to native types (suitable for json encoding). """ + # cache car très utilisé par anciens codes + key = (self.id, convert_objects, with_module_ue_coefs) + _cache = getattr(g, "_ue_to_dict_cache", None) + if _cache: + result = g._ue_to_dict_cache.get(key, False) + if result is not False: + return result + else: + g._ue_to_dict_cache = {} + _cache = g._ue_to_dict_cache + e = dict(self.__dict__) e.pop("_sa_instance_state", None) e.pop("evaluation_ue_poids", None) @@ -133,6 +144,7 @@ class UniteEns(db.Model): ] else: e.pop("module_ue_coefs", None) + _cache[key] = e return e def annee(self) -> int: @@ -180,12 +192,23 @@ class UniteEns(db.Model): le parcours indiqué. """ if parcour is not None: + key = (parcour.id, self.id, only_parcours) + ue_ects_cache = getattr(g, "_ue_ects_cache", None) + if ue_ects_cache: + ects = g._ue_ects_cache.get(key, False) + if ects is not False: + return ects + else: + g._ue_ects_cache = {} + ue_ects_cache = g._ue_ects_cache ue_parcour = UEParcours.query.filter_by( ue_id=self.id, parcours_id=parcour.id ).first() if ue_parcour is not None and ue_parcour.ects is not None: + ue_ects_cache[key] = ue_parcour.ects return ue_parcour.ects if only_parcours: + ue_ects_cache[key] = None return None return self.ects