From e2f3ddadef63c1bda330797740836e00c10fe448 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 11:28:36 +0100 Subject: Nettoyage des imports --- admin.py | 2 +- views.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/admin.py b/admin.py index 76b7f2d..f818865 100644 --- a/admin.py +++ b/admin.py @@ -15,7 +15,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from django.contrib import admin -from edt.models import Timetable, LastUpdate, Group, Subscription, Room, Course +from .models import Timetable, LastUpdate, Group, Subscription, Room, Course @admin.register(Timetable) diff --git a/views.py b/views.py index 273720a..08a450f 100644 --- a/views.py +++ b/views.py @@ -22,9 +22,9 @@ from django.core.mail import send_mail from django.conf import settings from django.template import Context, loader -from edt.forms import SubscribeForm -from edt.models import Timetable, LastUpdate, Group, Subscription, Course -from edt.utils import get_current_week, get_week, group_courses +from .forms import SubscribeForm +from .models import Timetable, LastUpdate, Group, Subscription, Course +from .utils import get_current_week, get_week, group_courses import datetime -- cgit v1.2.1 From 5ebf37dddf5ee8bb8dbc9c167ebb30c7fc537e19 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 11:44:29 +0100 Subject: Ajout d'une propriété dans les groupes pour récupérer le tuple des informations du groupe --- models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/models.py b/models.py index 2100d35..0d3f2c0 100644 --- a/models.py +++ b/models.py @@ -75,6 +75,10 @@ class Group(models.Model): def corresponds_to(self, timetable_id, mention, subgroup, td, tp): return self.timetable.id == timetable_id and self.mention == mention and self.subgroup == subgroup and (self.td == td or self.td is None or td is None) and (self.tp == tp or self.tp is None or tp is None) + @property + def group_info(self): + return self.timetable.id, self.mention, self.subgroup, self.td, self.tp + def __str__(self): return self.name -- cgit v1.2.1 From addaa7c09761107f589585fecf8af897f9f01b2c Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 11:55:14 +0100 Subject: Ajout de tests unitaires pour les groupes --- tests.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/tests.py b/tests.py index 42ddd65..4825f91 100644 --- a/tests.py +++ b/tests.py @@ -15,5 +15,68 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from django.test import TestCase +from .models import Timetable, Group -# Create your tests here. + +class GroupTestCase(TestCase): + def setUp(self): + self.timetable = Timetable(name="Test timetable", url="http://example.com/", slug="test-timetable") + self.timetable.save() + + Group.objects.create(celcat_name="L1 info s2 - CMA", timetable=self.timetable) + Group.objects.create(celcat_name="L1 info s2 - TDA2", timetable=self.timetable) + Group.objects.create(celcat_name="L1 info s2 - TPA21", timetable=self.timetable) + + Group.objects.create(celcat_name="L1 info s2 - CMB", timetable=self.timetable) + Group.objects.create(celcat_name="L1 info s2 - TDB2", timetable=self.timetable) + Group.objects.create(celcat_name="L1 info s2 - TPB21", timetable=self.timetable) + + def test_corresponds(self): + cma = Group.objects.get(celcat_name="L1 info s2 - CMA", timetable=self.timetable) + tda2 = Group.objects.get(celcat_name="L1 info s2 - TDA2", timetable=self.timetable) + tpa21 = Group.objects.get(celcat_name="L1 info s2 - TPA21", timetable=self.timetable) + + cmb = Group.objects.get(celcat_name="L1 info s2 - CMB", timetable=self.timetable) + tdb2 = Group.objects.get(celcat_name="L1 info s2 - TDB2", timetable=self.timetable) + tpb21 = Group.objects.get(celcat_name="L1 info s2 - TPB21", timetable=self.timetable) + + self.assertTrue(cma.corresponds_to(*tda2.group_info)) # CMA corresponds to TDA2 + self.assertTrue(cma.corresponds_to(*tpa21.group_info)) # CMA corresponds to TPA21 + self.assertTrue(tda2.corresponds_to(*tpa21.group_info)) # TDA2 corresponds to TPA21 + + self.assertTrue(cmb.corresponds_to(*tdb2.group_info)) # CMB corresponds to TDB2 + self.assertTrue(cmb.corresponds_to(*tpb21.group_info)) # CMB corresponds to TPB21 + self.assertTrue(tdb2.corresponds_to(*tpb21.group_info)) # TDB2 corresponds to TPB21 + + self.assertFalse(cmb.corresponds_to(*tda2.group_info)) # CMB does not corresponds to TDA2 + self.assertFalse(cmb.corresponds_to(*tpa21.group_info)) # CMB does not corresponds to TPA21 + self.assertFalse(tdb2.corresponds_to(*tpa21.group_info)) # TDB2 does not corresponds to TPA21 + + self.assertTrue(tda2.corresponds_to(*cma.group_info)) # TDA2 corresponds to CMA + self.assertTrue(tpa21.corresponds_to(*cma.group_info)) # TPA21 corresponds to CMA + self.assertTrue(tpa21.corresponds_to(*tda2.group_info)) # TPA21 corresponds to TDA2 + + self.assertTrue(tdb2.corresponds_to(*cmb.group_info)) # TDB2 corresponds to CMB + self.assertTrue(tpb21.corresponds_to(*cmb.group_info)) # TPB21 corresponds to CMB + self.assertTrue(tpb21.corresponds_to(*tdb2.group_info)) # TPB21 corresponds to TDB2 + + self.assertFalse(tda2.corresponds_to(*cmb.group_info)) # TDA2 does not corresponds to CMB + self.assertFalse(tpa21.corresponds_to(*cmb.group_info)) # TPA21 does not corresponds to CMB + self.assertFalse(tpa21.corresponds_to(*tdb2.group_info)) # TPA21 does not corresponds to TDB2 + + def test_parse(self): + cma = Group.objects.get(celcat_name="L1 info s2 - CMA", timetable=self.timetable) + tda2 = Group.objects.get(celcat_name="L1 info s2 - TDA2", timetable=self.timetable) + tpa21 = Group.objects.get(celcat_name="L1 info s2 - TPA21", timetable=self.timetable) + + cmb = Group.objects.get(celcat_name="L1 info s2 - CMB", timetable=self.timetable) + tdb2 = Group.objects.get(celcat_name="L1 info s2 - TDB2", timetable=self.timetable) + tpb21 = Group.objects.get(celcat_name="L1 info s2 - TPB21", timetable=self.timetable) + + self.assertEqual(cma.group_info, (self.timetable.id, "L1 info s2", "A", None, None)) + self.assertEqual(tda2.group_info, (self.timetable.id, "L1 info s2", "A", 2, None)) + self.assertEqual(tpa21.group_info, (self.timetable.id, "L1 info s2", "A", 2, 1)) + + self.assertEqual(cmb.group_info, (self.timetable.id, "L1 info s2", "B", None, None)) + self.assertEqual(tdb2.group_info, (self.timetable.id, "L1 info s2", "B", 2, None)) + self.assertEqual(tpb21.group_info, (self.timetable.id, "L1 info s2", "B", 2, 1)) -- cgit v1.2.1 From 30dc5ad8b5ae12ef9e7ea1fbb69e2b356dcc97da Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 12:01:45 +0100 Subject: Nouveau test pour les groupes --- tests.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests.py b/tests.py index 4825f91..3c58558 100644 --- a/tests.py +++ b/tests.py @@ -64,6 +64,23 @@ class GroupTestCase(TestCase): self.assertFalse(tpa21.corresponds_to(*cmb.group_info)) # TPA21 does not corresponds to CMB self.assertFalse(tpa21.corresponds_to(*tdb2.group_info)) # TPA21 does not corresponds to TDB2 + def test_get(self): + cma = Group.objects.get(name="L1 info s2 - CMA", timetable=self.timetable) + tda2 = Group.objects.get(name="L1 info s2 - TDA2", timetable=self.timetable) + tpa21 = Group.objects.get(name="L1 info s2 - TPA21", timetable=self.timetable) + + cmb = Group.objects.get(name="L1 info s2 - CMB", timetable=self.timetable) + tdb2 = Group.objects.get(name="L1 info s2 - TDB2", timetable=self.timetable) + tpb21 = Group.objects.get(name="L1 info s2 - TPB21", timetable=self.timetable) + + self.assertEqual(cma.celcat_name, "L1 info s2 - CMA") + self.assertEqual(tda2.celcat_name, "L1 info s2 - TDA2") + self.assertEqual(tpa21.celcat_name, "L1 info s2 - TPA21") + + self.assertEqual(cmb.celcat_name, "L1 info s2 - CMB") + self.assertEqual(tdb2.celcat_name, "L1 info s2 - TDB2") + self.assertEqual(tpb21.celcat_name, "L1 info s2 - TPB21") + def test_parse(self): cma = Group.objects.get(celcat_name="L1 info s2 - CMA", timetable=self.timetable) tda2 = Group.objects.get(celcat_name="L1 info s2 - TDA2", timetable=self.timetable) -- cgit v1.2.1 From 3f03f5a058755e166ec69d992b012186434caa18 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 12:32:01 +0100 Subject: Ajout de tests unitaires pour les cours --- tests.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/tests.py b/tests.py index 3c58558..b6b9a70 100644 --- a/tests.py +++ b/tests.py @@ -15,7 +15,41 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from django.test import TestCase -from .models import Timetable, Group +from django.utils import timezone + +from .models import Course, Group, Timetable + + +class CourseTestCase(TestCase): + def setUp(self): + dt = timezone.now() + + self.timetable = Timetable(name="Test timetable 2", url="http://example.org/", slug="test-timetable2") + self.timetable.save() + + cma = Group.objects.create(celcat_name="L1 info s2 - CMA", timetable=self.timetable) + tda2 = Group.objects.create(celcat_name="L1 info s2 - TDA2", timetable=self.timetable) + self.tpa21 = Group.objects.create(celcat_name="L1 info s2 - TPA21", timetable=self.timetable) + + cmb = Group.objects.create(celcat_name="L1 info s2 - CMB", timetable=self.timetable) + tdb2 = Group.objects.create(celcat_name="L1 info s2 - TDB2", timetable=self.timetable) + self.tpb21 = Group.objects.create(celcat_name="L1 info s2 - TPB21", timetable=self.timetable) + + for group in (cma, tda2, self.tpa21, cmb, tdb2, self.tpb21,): + course = Course.objects.create(name="{0} course".format(group.name), type="cours", timetable=self.timetable, begin=dt, end=dt) + course.groups.add(group) + + def test_get_courses_for_group(self): + tpa21_courses = Course.objects.get_courses_for_group(self.tpa21) + tpb21_courses = Course.objects.get_courses_for_group(self.tpb21) + + tpa21_course_names = ["L1 info s2 - CMA course", "L1 info s2 - TDA2 course", "L1 info s2 - TPA21 course"] + tpb21_course_names = ["L1 info s2 - CMB course", "L1 info s2 - TDB2 course", "L1 info s2 - TPB21 course"] + + for courses, names in ((tpa21_courses, tpa21_course_names,), (tpb21_courses, tpb21_course_names,),): + for course in courses: + self.assertIn(course.name, names) + names.remove(course.name) class GroupTestCase(TestCase): -- cgit v1.2.1 From 7dc44ec77c6adcf7515f382d439d9a1820085d73 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 12:34:20 +0100 Subject: Déplacement de ExtractWeek dans db.py --- db.py | 4 ++++ models.py | 6 +----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/db.py b/db.py index 678225e..80a8c95 100644 --- a/db.py +++ b/db.py @@ -22,6 +22,10 @@ from django.db.models.sql.query import Query from django.db.models.sql.where import WhereNode +class ExtractWeek(Extract): + lookup_name = "week" + + class GroupedCompiler(SQLCompiler): def get_group_by(self, select, order_by): result = super(GroupedCompiler, self).get_group_by(select, order_by) diff --git a/models.py b/models.py index 0d3f2c0..6d395e0 100644 --- a/models.py +++ b/models.py @@ -20,16 +20,12 @@ from django.db.models.expressions import RawSQL from django.db.models.functions import Extract, ExtractYear from django.utils.text import slugify -from .db import GroupedManager +from .db import ExtractWeek, GroupedManager import hashlib import os -class ExtractWeek(Extract): - lookup_name = "week" - - class Timetable(models.Model): name = models.CharField(max_length=64, unique=True, verbose_name="nom") url = models.URLField(max_length=255, unique=True, verbose_name="URL") -- cgit v1.2.1 From 64f7dedf227a88bac522cb34c6a99982b3d65321 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 12:55:19 +0100 Subject: Imports des modules pour ExtractWeek --- db.py | 4 ++-- models.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/db.py b/db.py index 80a8c95..94df376 100644 --- a/db.py +++ b/db.py @@ -16,11 +16,11 @@ from django.db import connections from django.db.models import Manager -from django.db.models.query import QuerySet +from django.db.models.functions import Extract from django.db.models.sql.compiler import SQLCompiler from django.db.models.sql.query import Query from django.db.models.sql.where import WhereNode - +from django.db.models.query import QuerySet class ExtractWeek(Extract): lookup_name = "week" diff --git a/models.py b/models.py index 6d395e0..1723536 100644 --- a/models.py +++ b/models.py @@ -17,7 +17,7 @@ from django.db import connection, models from django.db.models import Q from django.db.models.expressions import RawSQL -from django.db.models.functions import Extract, ExtractYear +from django.db.models.functions import ExtractYear from django.utils.text import slugify from .db import ExtractWeek, GroupedManager -- cgit v1.2.1 From bb5c77bf35b13f5c11bc4cdbc0325983e349b984 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sat, 11 Feb 2017 13:58:41 +0100 Subject: Squashed commit of the following: commit ff25e2dc285c423f4c40a83deb89a56ee62b15a9 Author: Alban Gruin Date: Sat Feb 11 13:47:38 2017 +0100 Nettoyage du code de CourseManager commit 26a132d5d1fdb7fc9da827bbc9d5e409834fb954 Author: Alban Gruin Date: Sat Feb 11 13:45:14 2017 +0100 Suppression du GroupedManager et de toutes ses sous-classes --- db.py | 80 --------------------------------------------------------------- models.py | 29 +++++++++++------------ 2 files changed, 13 insertions(+), 96 deletions(-) delete mode 100644 db.py diff --git a/db.py b/db.py deleted file mode 100644 index 94df376..0000000 --- a/db.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (C) 2017 Alban Gruin -# -# celcatsanitizer is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# celcatsanitizer is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with celcatsanitizer; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from django.db import connections -from django.db.models import Manager -from django.db.models.functions import Extract -from django.db.models.sql.compiler import SQLCompiler -from django.db.models.sql.query import Query -from django.db.models.sql.where import WhereNode -from django.db.models.query import QuerySet - -class ExtractWeek(Extract): - lookup_name = "week" - - -class GroupedCompiler(SQLCompiler): - def get_group_by(self, select, order_by): - result = super(GroupedCompiler, self).get_group_by(select, order_by) - expressions = [] - for expr in self.query.real_group_by: - ref = expr if hasattr(expr, "as_sql") else self.query.resolve_ref(expr) - sql, params = self.compile(ref) - result.append((sql, params)) - - return result - - -class GroupedQuery(Query): - def __init__(self, model, where=WhereNode): - super(GroupedQuery, self).__init__(model, where) - self.real_group_by = [] - - def clone(self, klass=None, memo=None, **kwargs): - obj = super(GroupedQuery, self).clone(klass, memo, **kwargs) - obj.real_group_by = self.real_group_by[:] - return obj - - def add_grouping(self, *grouping): - self.real_group_by.extend(grouping) - - def clear_grouping(self): - self.real_group_by = [] - - def get_compiler(self, using=None, connection=None): - if using is None and connection is None: - raise ValueError("Need either using or connection") - if using: - connection = connections[using] - return GroupedCompiler(self, connection, using) - - -class GroupedQuerySet(QuerySet): - def __init__(self, model=None, query=None, using=None, hints=None): - super(GroupedQuerySet, self).__init__(model, query, using, hints) - self.query = query or GroupedQuery(self.model) - - def group_by(self, *field_names): - obj = self._clone() - obj.query.clear_grouping() - obj.query.add_grouping(*field_names) - return obj - - -class GroupedManager(Manager): - def __init__(self): - super(GroupedManager, self).__init__() - self._queryset_class = GroupedQuerySet diff --git a/models.py b/models.py index 1723536..1e96a88 100644 --- a/models.py +++ b/models.py @@ -15,17 +15,19 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from django.db import connection, models -from django.db.models import Q +from django.db.models import Count, Manager, Q from django.db.models.expressions import RawSQL -from django.db.models.functions import ExtractYear +from django.db.models.functions import Extract, ExtractYear from django.utils.text import slugify -from .db import ExtractWeek, GroupedManager - import hashlib import os +class ExtractWeek(Extract): + lookup_name = "week" + + class Timetable(models.Model): name = models.CharField(max_length=64, unique=True, verbose_name="nom") url = models.URLField(max_length=255, unique=True, verbose_name="URL") @@ -141,22 +143,17 @@ class Room(models.Model): verbose_name_plural = "salles" -class CourseManager(GroupedManager): - def __get_weeks(self, qs): - extractYear = ExtractYear("begin") - qs = qs.group_by("groups", "year", "week", "groups__timetable", "groups__mention", "groups__subgroup", "groups__td", "groups__tp", "begin", "groups__name").order_by("groups__name", "year", "week") - - if connection.vendor == "postgresql": - return qs.annotate(week=ExtractWeek("begin"), year=extractYear) - else: - return qs.annotate(week=RawSQL("""cast(strftime("%%W", "begin") as integer)""", []), year=extractYear) - +class CourseManager(Manager): def get_courses_for_group(self, group, **filters): return self.get_queryset().filter(Q(groups__td__isnull=True) | Q(groups__td=group.td), Q(groups__tp__isnull=True) | Q(groups__tp=group.tp), groups__mention=group.mention, groups__subgroup=group.subgroup, timetable=group.timetable, **filters).order_by("begin") def get_weeks(self, **criteria): - qs = self.get_queryset().filter(**criteria) - return self.__get_weeks(qs) + qs = self.get_queryset().filter(**criteria).order_by("groups__name", "year", "week").annotate(_=Count(("groups", "year", "week", "begin")), year=ExtractYear("begin")) + + if connection.vendor == "postgresql": + return qs.annotate(week=ExtractWeek("begin")) + else: + return qs.annotate(week=RawSQL("""cast(strftime("%%W", "begin") as integer)""", [])) class Course(models.Model): -- cgit v1.2.1 From 6bb960804653efe4b0da436d01d9d9855090f82a Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sun, 12 Feb 2017 12:30:30 +0100 Subject: Refonte du système d'envoi des mails. N'envoie plus de mails si l'emploi du temps est vide --- management/commands/sendmails.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/management/commands/sendmails.py b/management/commands/sendmails.py index 3126243..dca7222 100644 --- a/management/commands/sendmails.py +++ b/management/commands/sendmails.py @@ -14,17 +14,29 @@ # with celcatsanitizer; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +from django.conf import settings from django.core.management.base import BaseCommand, CommandError from django.core.mail import send_mass_mail +from django.db.models import Count from django.utils import timezone, translation from django.template import Context, loader -from django.conf import settings from edt.models import Group, Subscription, Course from edt.utils import get_current_or_next_week, get_week, group_courses import datetime +def __generate_mails(start, end): + subscribed_groups = Subscription.objects.filter(active=True).annotate(nb=Count("group")) + for subscription in subscribed_groups: + courses = Course.objects.get_courses_for_group(subscription.group, begin__gte=start, begin__lt=end) + if len(courses) > 0: + grouped_courses = group_courses(courses) + + template = loader.get_template("mail/mail_timetable.txt") + context = Context({"subscription": subscription, "courses": grouped_couses, "week": week}) + yield subscription.group, template.render(context) + class Command(BaseCommand): help = "Sends emails to subscribed users" @@ -35,25 +47,19 @@ class Command(BaseCommand): year, week = get_current_or_next_week() start, end = get_week(year, week) - subscriptions = Subscription.objects.filter(active=True) - content = {} + footer = loader.get_template("mail/mail_footer.txt") mails = [] print("Generating messages...") - for subscription in subscriptions: - if subscription.group.id not in content: - courses = Course.objects.get_courses_for_group(subscription.group, begin__gte=start, begin__lt=end) - grouped_courses = group_courses(courses) - - template = loader.get_template("mail/mail_timetable.txt") - context = Context({"subscription": subscription, "courses": grouped_courses, "week": week}) - content[subscription.group.id] = template.render(context) + for group, content in __generate_mails(start, end): + subscriptions = Subscription.objects.filter(active=True, group=group) + title = "{0} - {1} - Semaine {2}".format(subscription.group.timetable.name, subscription.group.name, week) - footer = loader.get_template("mail/mail_footer.txt") - context = Context({"admins": settings.ADMINS, "token": subscription.token, "domain": settings.DEFAULT_DOMAIN}) - mail_content = content[subscription.group.id] + footer.render(context) + for subscription in subscriptions: + context = Context({"admins": settings.ADMINS, "token": subscription.token, "domain": settings.DEFAULT_DOMAIN}) + mail_content = content + footer.render(context) - mails.append(("{0} - {1} - Semaine {2}".format(subscription.group.timetable.name, subscription.group.name, week), mail_content, settings.DEFAULT_FROM_EMAIL, [subscription.email],)) + mails.append((title, mail_content, settings.DEFAULT_FROM_EMAIL, [subscription.email],)) print("Sending mails...") send_mass_mail(mails) -- cgit v1.2.1 From 9be6d21a548a1a041fdf52791fde96cc49092682 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sun, 12 Feb 2017 13:25:51 +0100 Subject: Affichage d'un message si il n'y a pas de cours enregitré pour un groupe Tri des emplois du temps par nom --- templates/index.html | 2 +- views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/index.html b/templates/index.html index 3170aea..d834884 100644 --- a/templates/index.html +++ b/templates/index.html @@ -62,7 +62,7 @@ li.course {

{{ timetable.name }}

{% endfor %}{% endblock %} diff --git a/views.py b/views.py index 08a450f..c573589 100644 --- a/views.py +++ b/views.py @@ -29,7 +29,7 @@ from .utils import get_current_week, get_week, group_courses import datetime def index(request): - timetables = Timetable.objects.all() + timetables = Timetable.objects.all().order_by("name") groups = Group.objects.filter(tp__isnull=False).order_by("name") year, week = get_current_week() -- cgit v1.2.1 From 8d382e5fa2107398d8793483674d50d768cd3029 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sun, 12 Feb 2017 13:30:55 +0100 Subject: Erreur 404 au lieu de 500 si une semaine n'est pas trouvée --- views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views.py b/views.py index c573589..651533a 100644 --- a/views.py +++ b/views.py @@ -59,8 +59,8 @@ def timetable(request, timetable_slug, group_slug, year=None, week=None): timetable = get_object_or_404(Timetable, slug=timetable_slug) group = get_object_or_404(Group, slug=group_slug, timetable=timetable) + last_update = get_object_or_404(LastUpdate, timetable=timetable, week=week, year=year) courses = Course.objects.get_courses_for_group(group, begin__gte=start, begin__lt=end) - last_update = LastUpdate.objects.get(timetable=timetable, week=week, year=year) grouped_courses = group_courses(courses) -- cgit v1.2.1 From 858efca050037de588a2ac813de4ac772458ed8c Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sun, 12 Feb 2017 13:36:56 +0100 Subject: Revert "Refonte du système d'envoi des mails. N'envoie plus de mails si l'emploi du temps est vide" This reverts commit 6bb960804653efe4b0da436d01d9d9855090f82a. --- management/commands/sendmails.py | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/management/commands/sendmails.py b/management/commands/sendmails.py index dca7222..3126243 100644 --- a/management/commands/sendmails.py +++ b/management/commands/sendmails.py @@ -14,29 +14,17 @@ # with celcatsanitizer; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -from django.conf import settings from django.core.management.base import BaseCommand, CommandError from django.core.mail import send_mass_mail -from django.db.models import Count from django.utils import timezone, translation from django.template import Context, loader +from django.conf import settings from edt.models import Group, Subscription, Course from edt.utils import get_current_or_next_week, get_week, group_courses import datetime -def __generate_mails(start, end): - subscribed_groups = Subscription.objects.filter(active=True).annotate(nb=Count("group")) - for subscription in subscribed_groups: - courses = Course.objects.get_courses_for_group(subscription.group, begin__gte=start, begin__lt=end) - if len(courses) > 0: - grouped_courses = group_courses(courses) - - template = loader.get_template("mail/mail_timetable.txt") - context = Context({"subscription": subscription, "courses": grouped_couses, "week": week}) - yield subscription.group, template.render(context) - class Command(BaseCommand): help = "Sends emails to subscribed users" @@ -47,19 +35,25 @@ class Command(BaseCommand): year, week = get_current_or_next_week() start, end = get_week(year, week) - footer = loader.get_template("mail/mail_footer.txt") + subscriptions = Subscription.objects.filter(active=True) + content = {} mails = [] print("Generating messages...") - for group, content in __generate_mails(start, end): - subscriptions = Subscription.objects.filter(active=True, group=group) - title = "{0} - {1} - Semaine {2}".format(subscription.group.timetable.name, subscription.group.name, week) + for subscription in subscriptions: + if subscription.group.id not in content: + courses = Course.objects.get_courses_for_group(subscription.group, begin__gte=start, begin__lt=end) + grouped_courses = group_courses(courses) + + template = loader.get_template("mail/mail_timetable.txt") + context = Context({"subscription": subscription, "courses": grouped_courses, "week": week}) + content[subscription.group.id] = template.render(context) - for subscription in subscriptions: - context = Context({"admins": settings.ADMINS, "token": subscription.token, "domain": settings.DEFAULT_DOMAIN}) - mail_content = content + footer.render(context) + footer = loader.get_template("mail/mail_footer.txt") + context = Context({"admins": settings.ADMINS, "token": subscription.token, "domain": settings.DEFAULT_DOMAIN}) + mail_content = content[subscription.group.id] + footer.render(context) - mails.append((title, mail_content, settings.DEFAULT_FROM_EMAIL, [subscription.email],)) + mails.append(("{0} - {1} - Semaine {2}".format(subscription.group.timetable.name, subscription.group.name, week), mail_content, settings.DEFAULT_FROM_EMAIL, [subscription.email],)) print("Sending mails...") send_mass_mail(mails) -- cgit v1.2.1 From 908ed3b4d0bc57131f6dafc663c6f7e098f0b7e1 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sun, 12 Feb 2017 13:39:02 +0100 Subject: N'envoie pas de mail si jamais il n'y a pas de cours pour une semaine --- management/commands/sendmails.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/management/commands/sendmails.py b/management/commands/sendmails.py index 3126243..5a2054f 100644 --- a/management/commands/sendmails.py +++ b/management/commands/sendmails.py @@ -38,22 +38,25 @@ class Command(BaseCommand): subscriptions = Subscription.objects.filter(active=True) content = {} mails = [] + footer = loader.get_template("mail/mail_footer.txt") print("Generating messages...") for subscription in subscriptions: if subscription.group.id not in content: courses = Course.objects.get_courses_for_group(subscription.group, begin__gte=start, begin__lt=end) - grouped_courses = group_courses(courses) - template = loader.get_template("mail/mail_timetable.txt") - context = Context({"subscription": subscription, "courses": grouped_courses, "week": week}) - content[subscription.group.id] = template.render(context) + if len(courses) > 0: + grouped_courses = group_courses(courses) - footer = loader.get_template("mail/mail_footer.txt") - context = Context({"admins": settings.ADMINS, "token": subscription.token, "domain": settings.DEFAULT_DOMAIN}) - mail_content = content[subscription.group.id] + footer.render(context) + template = loader.get_template("mail/mail_timetable.txt") + context = Context({"subscription": subscription, "courses": grouped_courses, "week": week}) + content[subscription.group.id] = template.render(context) - mails.append(("{0} - {1} - Semaine {2}".format(subscription.group.timetable.name, subscription.group.name, week), mail_content, settings.DEFAULT_FROM_EMAIL, [subscription.email],)) + if subscription.group.id in content: + context = Context({"admins": settings.ADMINS, "token": subscription.token, "domain": settings.DEFAULT_DOMAIN}) + mail_content = content[subscription.group.id] + footer.render(context) + + mails.append(("{0} - {1} - Semaine {2}".format(subscription.group.timetable.name, subscription.group.name, week), mail_content, settings.DEFAULT_FROM_EMAIL, [subscription.email],)) print("Sending mails...") send_mass_mail(mails) -- cgit v1.2.1