Skip to content
Snippets Groups Projects

Resolve "Django 3.2 database improvements"

Merged Jonathan Weth requested to merge 125-django-3-2-database-improvements into master
2 files
+ 39
37
Compare changes
  • Side-by-side
  • Inline
Files
2
@@ -4,7 +4,7 @@ from typing import Dict, Iterable, List, Optional, Union
from django.contrib.sites.managers import CurrentSiteManager as _CurrentSiteManager
from django.db import models
from django.db.models import Count, ExpressionWrapper, F, Func, Q, QuerySet, Value
from django.db.models import ExpressionWrapper, F, Func, Q, QuerySet, Value
from django.db.models.fields import DateField
from django.db.models.functions import Concat
@@ -97,7 +97,12 @@ class LessonPeriodManager(CurrentSiteManager):
"lesson__validity",
"lesson__validity__school_term",
)
.prefetch_related("lesson__groups", "lesson__teachers", "substitutions")
.prefetch_related(
"lesson__groups",
"lesson__groups__parent_groups",
"lesson__teachers",
"substitutions",
)
)
@@ -209,6 +214,13 @@ class WeekQuerySetMixin:
_year=models.Value(week.year, models.IntegerField()),
)
def alias_week(self, week: Union[CalendarWeek]):
"""Add an alias to all lessons in the QuerySet with the number of the provided calendar week."""
return self.alias(
_week=models.Value(week.week, models.IntegerField()),
_year=models.Value(week.year, models.IntegerField()),
)
class GroupByPeriodsMixin:
def group_by_periods(self, is_week: bool = False) -> dict:
@@ -541,21 +553,13 @@ class LessonSubstitutionQuerySet(LessonDataQuerySet):
Return all teachers which are affected by
selected substitutions (as substituted or substituting).
"""
return (
Person.objects.filter(
Q(lessons_as_teacher__in=self.affected_lessons()) | Q(lesson_substitutions__in=self)
)
.annotate(lessons_count=Count("lessons_as_teacher"))
.order_by("short_name")
)
return Person.objects.filter(
Q(lessons_as_teacher__in=self.affected_lessons()) | Q(lesson_substitutions__in=self)
).order_by("short_name")
def affected_groups(self):
"""Return all groups which are affected by selected substitutions."""
return (
Group.objects.filter(lessons__in=self.affected_lessons())
.annotate(lessons_count=Count("lessons"))
.order_by("short_name")
)
return Group.objects.filter(lessons__in=self.affected_lessons()).order_by("short_name")
class DateRangeQuerySetMixin:
@@ -596,25 +600,13 @@ class AbsenceQuerySet(DateRangeQuerySetMixin, SchoolTermRelatedQuerySet):
"""QuerySet with custom query methods for absences."""
def absent_teachers(self):
return (
Person.objects.filter(absences__in=self)
.annotate(absences_count=Count("absences"))
.order_by("short_name")
)
return Person.objects.filter(absences__in=self).order_by("short_name")
def absent_groups(self):
return (
Group.objects.filter(absences__in=self)
.annotate(absences_count=Count("absences"))
.order_by("short_name")
)
return Group.objects.filter(absences__in=self).order_by("short_name")
def absent_rooms(self):
return (
Person.objects.filter(absences__in=self)
.annotate(absences_count=Count("absences"))
.order_by("short_name")
)
return Person.objects.filter(absences__in=self).order_by("short_name")
class HolidayQuerySet(QuerySet, DateRangeQuerySetMixin):
@@ -736,6 +728,10 @@ class EventQuerySet(DateRangeQuerySetMixin, SchoolTermRelatedQuerySet, Timetable
"""Annotate all events in the QuerySet with the provided date."""
return self.annotate(_date=models.Value(day, models.DateField()))
def alias_day(self, day: date):
"""Add an alias to all events in the QuerySet with the provided date."""
return self.alias(_date=models.Value(day, models.DateField()))
class ExtraLessonQuerySet(TimetableQuerySet, SchoolTermRelatedQuerySet, GroupByPeriodsMixin):
"""QuerySet with custom query methods for extra lessons."""
@@ -744,14 +740,15 @@ class ExtraLessonQuerySet(TimetableQuerySet, SchoolTermRelatedQuerySet, GroupByP
def within_dates(self, start: date, end: date):
"""Filter all extra lessons within a specific time range."""
return self.annotate_day().filter(day__gte=start, day__lte=end)
return self.alias_day().filter(day__gte=start, day__lte=end)
def on_day(self, day: date):
"""Filter all extra lessons on a day."""
return self.within_dates(day, day)
def annotate_day(self):
weekday_to_date = ExpressionWrapper(
def _get_weekday_to_date(self):
"""Get DB function to convert a weekday to a date."""
return ExpressionWrapper(
Func(
Concat(F("year"), F("week")),
Value("IYYYIW"),
@@ -761,14 +758,19 @@ class ExtraLessonQuerySet(TimetableQuerySet, SchoolTermRelatedQuerySet, GroupByP
+ F("period__weekday"),
output_field=DateField(),
)
return self.annotate(day=weekday_to_date)
def annotate_day(self):
return self.annotate(day=self._get_weekday_to_date())
def alias_day(self):
return self.alias(day=self._get_weekday_to_date())
def exclude_holidays(self, holidays: Iterable["Holiday"]) -> QuerySet:
"""Exclude all extra lessons which are in the provided holidays."""
q = Q()
for holiday in holidays:
q = q | Q(day__lte=holiday.date_end, day__gte=holiday.date_start)
return self.annotate_day().exclude(q)
return self.alias_day().exclude(q)
class GroupPropertiesMixin:
Loading