From ee94b9e48dc2b632f876702df57136f394ee5574 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 27 Jan 2018 19:57:02 +0100 Subject: Requête de QSJPS Pour chaque salle, on compte tous les cours commençant avant la fin de l’intervalle entré par l’utilisateur et finissant après le début de cet intervalle. Tous les cours correspondant à cette requête se trouvent au moins en partie sur l’intervalle. On sélectionne ensuite les salles n’ayant pas de cours correspondant à la requête précédente. --- models.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'models.py') diff --git a/models.py b/models.py index 1a638ac..e907944 100644 --- a/models.py +++ b/models.py @@ -16,7 +16,7 @@ from functools import reduce from django.db import models -from django.db.models import Manager, Q +from django.db.models import Manager, OuterRef, Q, Subquery, Value from django.db.models.functions import ExtractWeek, ExtractYear from django.utils import timezone from django.utils.text import slugify @@ -162,7 +162,26 @@ class Group(SlugModel): class RoomManager(Manager): def qsjps(self, begin, end): - return None + # 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é. + 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 class Room(SlugModel): -- cgit v1.2.1