diff options
author | Alban Gruin | 2018-01-27 21:59:42 +0100 |
---|---|---|
committer | Alban Gruin | 2018-01-27 21:59:42 +0100 |
commit | 0aceecf04cf720525772a9801d7799f19e5a3cd1 (patch) | |
tree | 398c26c5a558ae4d52d725a4ea353fd9230cbbc3 | |
parent | ee94b9e48dc2b632f876702df57136f394ee5574 (diff) |
Remplacement de la requête de QSJPS par une autre, plus simple et plus
rapide à exécuter sur de gros volumes de données. On aura peut-être
besoin d’utiliser un double index pour augmenter encore plus les
performances.
La requête liste tous les cours commençant avant la fin de
l’intervalle et finissant après le début de l’intervalle, en excluant
les cours n’ayant pas de salle assignée. On récupère ensuite la liste
des salles de ces cours, et on inverse le contenu de la liste. On trie
ensuite les cours par leur nom.
-rw-r--r-- | models.py | 33 |
1 files changed, 13 insertions, 20 deletions
@@ -16,7 +16,7 @@ from functools import reduce from django.db import models -from django.db.models import Manager, OuterRef, Q, Subquery, Value +from django.db.models import Manager, Q from django.db.models.functions import ExtractWeek, ExtractYear from django.utils import timezone from django.utils.text import slugify @@ -162,26 +162,19 @@ class Group(SlugModel): class RoomManager(Manager): def qsjps(self, begin, end): - # On compte tous les cours correspondant à chaque salle - # commençant avant la fin de l’intervalle et finissant après - # le début de l’intervalle. Ces cours se trouvent à un moment - # dans l’intervalle, et la salle assignée à ce cours ne peut - # donc pas être sélectionnée. Pour accélérer la requête, on - # s’arrête au premier cours trouvé. + # On récupère la liste des cours qui commencent avant la fin + # de l’intervalle sélectionné et qui terminent après le début + # de l’intervalle, c’est-à-dire qu’au moins une partie du + # cours se déroule pendant l’intervalle. On récupère ensuite + # la liste des salles dans lesquelles se déroulent ces + # cours. On exclu les cours n’ayant aucune salle assignée. courses = Course.objects.filter(begin__lt=end, end__gt=begin, - rooms=OuterRef("pk")) \ - .annotate(c=Value(1, - output_field=models.IntegerField())) \ - .values_list("c", flat=True)[:1] - - # On sélectionne toutes les salles qui n’ont aucun de cours se - # trouvant au moins en partie dans l’intervalle entré par - # l’utilisateur. - rooms = self.get_queryset().annotate( - c=Subquery(courses, output_field=models.IntegerField())) \ - .filter(c__isnull=True).order_by("name") - - return rooms + rooms__isnull=False) \ + .values_list("rooms", flat=True) + + # On sélectionne ensuite les salles qui ne sont pas dans la + # liste récupérée plus haut, et on les trie par leur nom. + return self.get_queryset().exclude(pk__in=courses).order_by("name") class Room(SlugModel): |