Skip to content

Commit

Permalink
Add the ability to mark a semester as active
Browse files Browse the repository at this point in the history
This will help us prepare lessons before a semester starts, without having to offset the beginning weeks.
  • Loading branch information
Kobzol committed Sep 8, 2024
1 parent 84a2787 commit 39642a9
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 18 deletions.
12 changes: 7 additions & 5 deletions api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
Semester,
Subject,
assignedtask_results,
current_semester_conds,
current_semester,
submit_assignment_path,
)
Expand Down Expand Up @@ -202,13 +201,17 @@ def sort_fn(c):


@user_passes_test(is_teacher)
def subject_list(request, subject_abbr):
def subject_list(request, subject_abbr: str):
"""
Returns the list of active classes for a given subject.
Used when creating a new task.
"""
get_object_or_404(
Subject, abbr=subject_abbr
) # The result is not needed, the call is to provide 404 error

classes = []
for clazz in Class.objects.filter(subject__abbr=subject_abbr, **current_semester_conds()):
for clazz in Class.objects.current_semester().filter(subject__abbr=subject_abbr):
classes.append(
{
"id": clazz.pk,
Expand Down Expand Up @@ -515,9 +518,8 @@ def is_allowed(path):
"type": "file",
}

classes = Class.objects.filter(
classes = Class.objects.current_semester().filter(
subject__abbr=task.subject.abbr,
**current_semester_conds(),
)
assigned_count = 0
for clazz in classes:
Expand Down
18 changes: 18 additions & 0 deletions common/migrations/0020_semester_active.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.16 on 2024-09-08 07:22

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('common', '0019_submit_ip_address'),
]

operations = [
migrations.AddField(
model_name='semester',
name='active',
field=models.BooleanField(default=False),
),
]
39 changes: 26 additions & 13 deletions common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import re
import logging

from typing import List
from typing import List, Optional

from django.db.models import QuerySet
from django.utils import timezone

from django.db import models
Expand All @@ -16,32 +17,44 @@
from jinja2 import Environment, FileSystemLoader


def current_semester_conds(prefix=""):
return {
f"{prefix}semester__begin__lte": timezone.now(),
f"{prefix}semester__end__gte": timezone.now(),
}


def current_semester() -> "Semester":
semester = Semester.objects.filter(begin__lte=timezone.now(), end__gte=timezone.now()).first()
def current_semester() -> Optional["Semester"]:
"""
Returns the current active semester, if there is any.
"""
semester = Semester.objects.filter(active=True).order_by("-begin").first()

if semester:
return semester

return Semester.objects.filter(begin__lte=timezone.now()).order_by("begin").last()
# If no semester is marked as active, return the latest semester that has already begun.
return Semester.objects.filter(begin__lte=timezone.now()).order_by("-begin").first()


class ClassManager(models.Manager):
def current_semester(self):
return self.filter(**current_semester_conds())
def current_semester(self) -> QuerySet:
"""
Return classes for the currently active semester.
Note that the semantics for this call are a bit less strict than for `current_semester`.
Notably, if multiple semesters are active, it will return classes for all of them.
We could create some query like
WHERE r.active=1 AND NOT
EXISTS (SELECT * FROM semester AS s WHERE s.active=1 AND r.id != s.id AND s.begin > r.begin)
But it seems like overkill, since we will only ever have exactly one active semester
(we just need to make sure in admin that this property holds).
"""
return self.filter(semester__active=True)


class Semester(models.Model):
begin = models.DateField()
end = models.DateField()
year = models.IntegerField()
winter = models.BooleanField()
# Is the semester currently marked as active?
# Ideally, only one semester should be marked as such.
active = models.BooleanField(default=False)

def __str__(self):
return f"{self.year}{'W' if self.winter else 'S'}"
Expand Down

0 comments on commit 39642a9

Please sign in to comment.