diff options
author | Alban Gruin | 2018-04-29 01:23:39 +0200 |
---|---|---|
committer | Alban Gruin | 2019-01-02 18:30:10 +0100 |
commit | 3b81ba3d9f29b792b0b9d9725b32d51a135248bc (patch) | |
tree | dbfca80358691315fc4fb7ccb8e68f60a103355d | |
parent | fd516af7aedf938cc6fb65eca556e8341a0dfd92 (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.py | 53 |
1 files changed, 36 insertions, 17 deletions
@@ -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}) |