aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlban Gruin2018-04-29 01:23:39 +0200
committerAlban Gruin2019-01-02 18:30:10 +0100
commit3b81ba3d9f29b792b0b9d9725b32d51a135248bc (patch)
treedbfca80358691315fc4fb7ccb8e68f60a103355d
parentfd516af7aedf938cc6fb65eca556e8341a0dfd92 (diff)
views: requête de liste des groupes/semaines opti pour PostgreSQLag/requete-groupe-opti-pg
La requête actuelle récupère une ligne par groupe/semaine de cours sans correspondance inter-groupe (TPA22 veut aussi les cours de TDA2, etc.), ce qui demande un post-traitement quadratique (voire peut-être pire) pour regrouper les semaines par groupe. Grace aux liste de PostgreSQL, il est possible de faire une requête éliminant le besoin de faire un post-traitement en Python. Cette requête sélectionne tous les groupes ayant la même source, la même mention, le même semestre et un sous-groupe qui ont les mêmes premiers caractères. Elle sélectionne ensuite tous les cours correspondant à ce groupe qui commencent entre l’heure actuelle sur une période de un mois. Ensuite, les dates sont tronquées au début de la semaine, triées, puis aggrégée sous forme de liste. Celle-ci est rajoutée comme entrée dans le groupe sélectionné. Le résultat peut être directement passé à une template. Cette requête est plus lente que l’ancienne, mais l’élimination de l’étape de post-traitement résulte en une accélération du rendu de la page. Signed-off-by: Alban Gruin <alban at pa1ch dot fr>
-rw-r--r--views.py53
1 files changed, 36 insertions, 17 deletions
diff --git a/views.py b/views.py
index e45ece3..fc6c1c2 100644
--- a/views.py
+++ b/views.py
@@ -57,23 +57,42 @@ def group_list(request, year_slug, timetable_slug):
groups = Group.objects.get_relevant_groups(start, source=timetable.source,
hidden=False)
- groups_weeks = Course.objects.get_weeks(begin__gte=start, begin__lt=end,
- groups__in=groups)
-
- for group in groups:
- for group_week in groups_weeks:
- if group.corresponds_to(group_week["groups__mention"],
- group_week["groups__semester"],
- group_week["groups__subgroup"]):
- if not hasattr(group, "weeks"):
- group.weeks = []
-
- date, _ = get_week(group_week["year"], group_week["week"])
- if date not in group.weeks:
- group.weeks.append(date)
-
- if hasattr(group, "weeks"):
- group.weeks.sort()
+
+ if connection.vendor == "postgresql":
+ weeks_sreq = RawSQL("""
+SELECT ARRAY_AGG(bw) FROM (
+ SELECT DATE_TRUNC('week', u2.begin) as bw FROM edt_group u0
+ LEFT OUTER JOIN edt_course_groups u1 ON (u0.id = u1.group_id)
+ LEFT OUTER JOIN edt_course u2 ON (u1.course_id = u2.id)
+ WHERE u0.source_id = edt_group.source_id AND
+ u0.mention = edt_group.mention AND
+ u0.semester = edt_group.semester AND
+ u0.subgroup = SUBSTRING(edt_group.subgroup, 1, LENGTH(u0.subgroup)) AND
+ u2.begin >= DATE_TRUNC('week', NOW()) AND
+ u2.begin < DATE_TRUNC('week', NOW() + '1 MONTH'::INTERVAL)
+ GROUP BY bw
+ ORDER BY bw
+) weeks""", [])
+ groups = groups.annotate(weeks=weeks_sreq)
+ else:
+ groups_weeks = Course.objects.get_weeks(begin__gte=start,
+ begin__lt=end,
+ groups__in=groups)
+
+ for group in groups:
+ for group_week in groups_weeks:
+ if group.corresponds_to(group_week["groups__mention"],
+ group_week["groups__semester"],
+ group_week["groups__subgroup"]):
+ if not hasattr(group, "weeks"):
+ group.weeks = []
+
+ date, _ = get_week(group_week["year"], group_week["week"])
+ if date not in group.weeks:
+ group.weeks.append(date)
+
+ if hasattr(group, "weeks"):
+ group.weeks.sort()
return render(request, "group_list.html",
{"timetable": timetable, "elements": groups})