From 8a375b6a7c2029d01393d64d7c274def39312e60 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Fri, 17 Apr 2020 12:48:34 +0200 Subject: [PATCH 1/3] Add/update __str__ methods for models --- aleksis/apps/chronos/models.py | 70 +++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py index 016204bc..c7689433 100644 --- a/aleksis/apps/chronos/models.py +++ b/aleksis/apps/chronos/models.py @@ -16,12 +16,14 @@ from django.http.request import QueryDict from django.urls import reverse from django.utils import timezone from django.utils.decorators import classproperty +from django.utils.formats import date_format from django.utils.translation import gettext_lazy as _ from calendarweek.django import CalendarWeek, i18n_day_names_lazy, i18n_day_abbrs_lazy from colorfield.fields import ColorField from django_global_request.middleware import get_request +from aleksis.apps.chronos.util.format import format_m2m from aleksis.core.mixins import ExtensibleModel from aleksis.core.models import Group, Person, DashboardWidget @@ -288,11 +290,9 @@ class TimePeriod(ExtensibleModel): time_end = models.TimeField(verbose_name=_("Time the period ends")) def __str__(self) -> str: - return "%s, %d. period (%s - %s)" % ( - self.weekday, + return "{}, {}.".format( + self.get_weekday_display(), self.period, - self.time_start, - self.time_end, ) @classmethod @@ -407,7 +407,7 @@ class Subject(ExtensibleModel): ) def __str__(self) -> str: - return "%s - %s" % (self.abbrev, self.name) + return "{} ({})".format(self.abbrev, self.name) class Meta: ordering = ["name", "abbrev"] @@ -462,6 +462,13 @@ class Lesson(ExtensibleModel): return CalendarWeek(year=year, week=week) + def __str__(self): + return "{}, {}, {}".format( + format_m2m(self.groups), + self.subject.abbrev, + format_m2m(self.teachers), + ) + class Meta: ordering = ["date_start", "subject"] indexes = [models.Index(fields=["date_start", "date_end"])] @@ -505,6 +512,14 @@ class LessonSubstitution(ExtensibleModel): else: return "substitution" + @property + def date(self): + week = CalendarWeek(week=self.week) + return week[self.lesson_period.period.weekday] + + def __str__(self): + return "{}, {}".format(str(self.lesson_period), date_format(self.date)) + class Meta: unique_together = [["lesson_period", "week"]] ordering = [ @@ -567,11 +582,9 @@ class LessonPeriod(ExtensibleModel): return self.lesson.groups def __str__(self) -> str: - return "%s, %d., %s, %s" % ( - self.period.get_weekday_display(), - self.period.period, - ", ".join(list(self.lesson.groups.values_list("short_name", flat=True))), - self.lesson.subject.name, + return "{}, {}".format( + str(self.period), + str(self.lesson) ) class Meta: @@ -651,6 +664,12 @@ class AbsenceReason(ExtensibleModel): short_name = models.CharField(verbose_name=_("Short name"), max_length=255) name = models.CharField(verbose_name=_("Name"), blank=True, null=True, max_length=255) + def __str__(self): + if self.name: + return "{} ({})".format(self.short_name, self.name) + else: + return self.short_name + class Meta: verbose_name = _("Absence reason") verbose_name_plural = _("Absence reasons") @@ -668,6 +687,16 @@ class Absence(ExtensibleModel): period_to = models.ForeignKey("TimePeriod", on_delete=models.CASCADE, verbose_name=_("Effective end period of absence"), null=True, related_name="+") comment = models.TextField(verbose_name=_("Comment"), blank=True, null=True) + def __str__(self): + if self.teacher: + return str(self.teacher) + elif self.group: + return str(self.group) + elif self.room: + return str(self.room) + else: + return _("Unknown absence") + class Meta: ordering = ["date_start"] indexes = [models.Index(fields=["date_start", "date_end"])] @@ -724,6 +753,9 @@ class Holiday(ExtensibleModel): return per_weekday + def __str__(self): + return self.title + class Meta: ordering = ["date_start"] indexes = [models.Index(fields=["date_start", "date_end"])] @@ -737,6 +769,9 @@ class SupervisionArea(ExtensibleModel): colour_fg = ColorField(default="#000000") colour_bg = ColorField() + def __str__(self): + return "{} ({})".format(self.name, self.short_name) + class Meta: ordering = ["name"] verbose_name = _("Supervision area") @@ -794,6 +829,9 @@ class Break(ExtensibleModel): return breaks + def __str__(self): + return "{} ({})".format(self.name, self.short_name) + class Meta: ordering = ["after_period"] indexes = [models.Index(fields=["after_period", "before_period"])] @@ -859,6 +897,9 @@ class Supervision(ExtensibleModel): def teachers(self): return [self.teacher] + def __str__(self): + return "{}, {}, {}".format(self.break_item, self.area, self.teacher) + class Meta: ordering = ["area", "break_item"] verbose_name= _("Supervision") @@ -874,6 +915,9 @@ class SupervisionSubstitution(ExtensibleModel): def teachers(self): return [self.teacher] + def __str__(self): + return "{}, {}".format(self.supervision, date_format(self.date)) + class Meta: ordering = ["date", "supervision"] verbose_name = _("Supervision substitution") @@ -953,6 +997,12 @@ class Event(ExtensibleModel): rooms = models.ManyToManyField("Room", related_name="events", verbose_name=_("Rooms")) teachers = models.ManyToManyField("core.Person", related_name="events", verbose_name=_("Teachers")) + def __str__(self): + if self.title: + return self.title + else: + return _("Event {}".format(self.pk)) + class Meta: ordering = ["date_start"] indexes = [models.Index(fields=["period_from", "period_to", "date_start", "date_end"])] -- GitLab From e01c9671ef84cc63335c21b2f4395ac89d2e64a0 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Fri, 17 Apr 2020 12:49:44 +0200 Subject: [PATCH 2/3] Add missing verbose names to models --- aleksis/apps/chronos/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py index c7689433..e023bb05 100644 --- a/aleksis/apps/chronos/models.py +++ b/aleksis/apps/chronos/models.py @@ -385,6 +385,8 @@ class TimePeriod(ExtensibleModel): unique_together = [["weekday", "period"]] ordering = ["weekday", "period"] indexes = [models.Index(fields=["time_start", "time_end"])] + verbose_name = _("Time period") + verbose_name_plural = _("Time periods") class Subject(ExtensibleModel): @@ -472,6 +474,8 @@ class Lesson(ExtensibleModel): class Meta: ordering = ["date_start", "subject"] indexes = [models.Index(fields=["date_start", "date_end"])] + verbose_name = _("Lesson") + verbose_name_plural = _("Lessons") class LessonSubstitution(ExtensibleModel): @@ -534,6 +538,8 @@ class LessonSubstitution(ExtensibleModel): name="either_substituted_or_cancelled", ) ] + verbose_name = _("Lesson substitution") + verbose_name_plural = _("Lesson substitutions") class LessonPeriod(ExtensibleModel): @@ -590,6 +596,8 @@ class LessonPeriod(ExtensibleModel): class Meta: ordering = ["lesson__date_start", "period__weekday", "period__period", "lesson__subject"] indexes = [models.Index(fields=["lesson", "period"])] + verbose_name = _("Lesson period") + verbose_name_plural = _("Lesson periods") class TimetableWidget(DashboardWidget): -- GitLab From 05ee82fd7bbf7881df78a6f04dfa469c569295dc Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Fri, 17 Apr 2020 12:50:52 +0200 Subject: [PATCH 3/3] Include models in Django admin --- aleksis/apps/chronos/admin.py | 186 +++++++++++++++++++++++++++- aleksis/apps/chronos/util/format.py | 9 ++ 2 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 aleksis/apps/chronos/util/format.py diff --git a/aleksis/apps/chronos/admin.py b/aleksis/apps/chronos/admin.py index b43af26c..816f9d16 100644 --- a/aleksis/apps/chronos/admin.py +++ b/aleksis/apps/chronos/admin.py @@ -1,5 +1,187 @@ from django.contrib import admin +from django.utils.html import format_html -from .models import TimetableWidget +from .models import ( + TimetableWidget, + Lesson, + LessonSubstitution, + SupervisionSubstitution, + LessonPeriod, + Absence, + Event, + Holiday, + Supervision, + Subject, + SupervisionArea, + Room, + AbsenceReason, + Break, + TimePeriod, +) +from .util.format import format_date_period, format_m2m -admin.site.register(TimetableWidget) + +def colour_badge(fg: str, bg: str, val: str): + html = """ + <div style=" + color: {}; + background-color: {}; + padding-top: 3px; + padding-bottom: 4px; + text-align: center; + border-radius: 3px; + ">{}</span> + """ + return format_html(html, fg, bg, val) + + +class AbsenceReasonAdmin(admin.ModelAdmin): + list_display = ("short_name", "name") + list_display_links = ("short_name", "name") + + +admin.site.register(AbsenceReason, AbsenceReasonAdmin) + + +class AbsenceAdmin(admin.ModelAdmin): + def start(self, obj): + return format_date_period(obj.date_start, obj.period_from) + + def end(self, obj): + return format_date_period(obj.date_end, obj.period_to) + + list_display = ("__str__", "reason", "start", "end") + + +admin.site.register(Absence, AbsenceAdmin) + + +class SupervisionInline(admin.TabularInline): + model = Supervision + + +class BreakAdmin(admin.ModelAdmin): + list_display = ("__str__", "after_period", "before_period") + inlines = [SupervisionInline] + + +admin.site.register(Break, BreakAdmin) + + +class EventAdmin(admin.ModelAdmin): + def start(self, obj): + return format_date_period(obj.date_start, obj.period_from) + + def end(self, obj): + return format_date_period(obj.date_end, obj.period_to) + + def _groups(self, obj): + return format_m2m(obj.groups) + + def _teachers(self, obj): + return format_m2m(obj.teachers) + + def _rooms(self, obj): + return format_m2m(obj.rooms) + + filter_horizontal = ("groups", "teachers", "rooms") + list_display = ("__str__", "_groups", "_teachers", "_rooms", "start", "end") + + +admin.site.register(Event, EventAdmin) + + +class HolidayAdmin(admin.ModelAdmin): + list_display = ("title", "date_start", "date_end") + + +admin.site.register(Holiday, HolidayAdmin) + + +class LessonPeriodInline(admin.TabularInline): + model = LessonPeriod + + +class LessonSubstitutionAdmin(admin.ModelAdmin): + list_display = ("lesson_period", "week", "date") + list_display_links = ("lesson_period", "week", "date") + filter_horizontal = ("teachers",) + + +admin.site.register(LessonSubstitution, LessonSubstitutionAdmin) + + +class LessonAdmin(admin.ModelAdmin): + def _groups(self, obj): + return format_m2m(obj.groups) + + def _teachers(self, obj): + return format_m2m(obj.teachers) + + filter_horizontal = ["teachers", "groups"] + inlines = [LessonPeriodInline] + list_filter = ("subject", "groups", "groups__parent_groups", "teachers") + list_display = ("_groups", "subject", "_teachers") + + +admin.site.register(Lesson, LessonAdmin) + + +class RoomAdmin(admin.ModelAdmin): + list_display = ("short_name", "name") + list_display_links = ("short_name", "name") + + +admin.site.register(Room, RoomAdmin) + + +class SubjectAdmin(admin.ModelAdmin): + def _colour(self, obj): + return colour_badge(obj.colour_fg, obj.colour_bg, obj.abbrev,) + + list_display = ("abbrev", "name", "_colour") + list_display_links = ("abbrev", "name") + + +admin.site.register(Subject, SubjectAdmin) + + +class SupervisionAreaAdmin(admin.ModelAdmin): + def _colour(self, obj): + return colour_badge(obj.colour_fg, obj.colour_bg, obj.short_name,) + + list_display = ("short_name", "name", "_colour") + list_display_links = ("short_name", "name") + inlines = [SupervisionInline] + + +admin.site.register(SupervisionArea, SupervisionAreaAdmin) + + +class SupervisionSubstitutionAdmin(admin.ModelAdmin): + list_display = ("supervision", "date") + + +admin.site.register(SupervisionSubstitution, SupervisionSubstitutionAdmin) + + +class SupervisionAdmin(admin.ModelAdmin): + list_display = ("break_item", "area", "teacher") + + +admin.site.register(Supervision, SupervisionAdmin) + + +class TimePeriodAdmin(admin.ModelAdmin): + list_display = ("weekday", "period", "time_start", "time_end") + list_display_links = ("weekday", "period") + + +admin.site.register(TimePeriod, TimePeriodAdmin) + + +class TimetableWidgetAdmin(admin.ModelAdmin): + list_display = ("title", "active") + + +admin.site.register(TimetableWidget, TimetableWidgetAdmin) diff --git a/aleksis/apps/chronos/util/format.py b/aleksis/apps/chronos/util/format.py new file mode 100644 index 00000000..c85668bf --- /dev/null +++ b/aleksis/apps/chronos/util/format.py @@ -0,0 +1,9 @@ +from django.utils.formats import date_format + + +def format_m2m(f, attr: str = "short_name"): + return ", ".join([getattr(x, attr) for x in f.all()]) + + +def format_date_period(date, period): + return "{}, {}.".format(date_format(date), period.period) -- GitLab