def course_view_data(request, slug) -> Tuple[Optional[CourseInstance], Optional[Dict]]: """Retrieves course and relevant data for the request. If course does not exist it returns two None objects. """ course: CourseInstance = None try: course = CourseInstance.objects.filter(slug=slug).select_related( 'semester', 'course_type').prefetch_related('tags', 'effects').get() except CourseInstance.DoesNotExist: return None, None student: Student = None if request.user.is_authenticated and request.user.student: student = request.user.student groups = course.groups.exclude(extra='hidden').select_related( 'teacher', 'teacher__user', ).prefetch_related('term', 'term__classrooms', 'guaranteed_spots', 'guaranteed_spots__role') # Collect the general groups statistics. groups_stats = Record.groups_stats(groups) # Collect groups information related to the student. student_status_groups = Record.is_recorded_in_groups(student, groups) student_can_enqueue = Record.can_enqueue_groups(student, course.groups.all()) student_can_dequeue = Record.can_dequeue_groups(student, course.groups.all()) for group in groups: group.num_enrolled = groups_stats.get(group.pk).get('num_enrolled') group.num_enqueued = groups_stats.get(group.pk).get('num_enqueued') group.is_enrolled = student_status_groups.get(group.pk).get('enrolled') group.is_enqueued = student_status_groups.get(group.pk).get('enqueued') group.priority = student_status_groups.get(group.pk).get('priority') group.can_enqueue = student_can_enqueue.get(group.pk) group.can_dequeue = student_can_dequeue.get(group.pk) teachers = {g.teacher for g in groups} course.is_enrollment_on = any(g.can_enqueue for g in groups) waiting_students = {} if request.user.employee: waiting_students = Record.list_waiting_students([course])[course.id] data = { 'course': course, 'teachers': teachers, 'groups': groups, 'waiting_students': waiting_students, } return course, data
def prototype_get_course(request, course_id): """Retrieves the annotated groups of a single course.""" student = request.user.student course = CourseInstance.objects.get(pk=course_id) groups = course.groups.exclude(extra='hidden').select_related( 'course', 'teacher', 'course__semester', 'teacher__user' ).prefetch_related('term', 'term__classrooms', 'guaranteed_spots', 'guaranteed_spots__role') can_enqueue_dict = Record.can_enqueue_groups(student, groups) can_dequeue_dict = Record.can_dequeue_groups(student, groups) for group in groups: group.can_enqueue = can_enqueue_dict.get(group.pk) group.can_dequeue = can_dequeue_dict.get(group.pk) group_dicts = build_group_list(groups) return JsonResponse(group_dicts, safe=False)
def my_prototype(request): """Renders the prototype with enrolled, enqueued, and pinned groups.""" student = request.user.student semester = Semester.objects.get_next() # This costs an additional join, but works if there is no current semester. records = Record.objects.filter( student=student, group__course__semester=semester).exclude(status=RecordStatus.REMOVED).select_related( 'group__teacher', 'group__teacher__user', 'group__course', 'group__course__semester').prefetch_related( 'group__term', 'group__term__classrooms', 'group__guaranteed_spots', 'group__guaranteed_spots__role') pinned = Pin.student_pins_in_semester(student, semester) pinned = list(pinned) all_groups_by_id = {r.group_id: r.group for r in records} all_groups_by_id.update({p.pk: p for p in pinned}) all_groups = list(all_groups_by_id.values()) can_enqueue_dict = Record.can_enqueue_groups(student, all_groups) can_dequeue_dict = Record.can_dequeue_groups(student, all_groups) for record in records: group = all_groups_by_id.get(record.group_id) group.is_enrolled = record.status == RecordStatus.ENROLLED group.is_enqueued = record.status == RecordStatus.QUEUED for pin in pinned: group = all_groups_by_id.get(pin.pk) group.is_pinned = True all_groups = all_groups_by_id.values() for group in all_groups: group.can_enqueue = can_enqueue_dict.get(group.pk) group.can_dequeue = can_dequeue_dict.get(group.pk) group_dicts = build_group_list(all_groups) filters_dict = CourseInstance.prepare_filter_data( CourseInstance.objects.filter(semester=semester)) courses_json = list_courses_in_semester(semester) data = { 'groups_json': json.dumps(group_dicts, cls=DjangoJSONEncoder), 'filters_json': json.dumps(filters_dict, cls=DjangoJSONEncoder), 'courses_json': courses_json, } return render(request, 'timetable/prototype.html', data)
def prototype_update_groups(request): """Retrieves the updated group annotations. The list of groups ids to update will be sent in JSON body of the request. """ student = request.user.student semester = Semester.objects.get_next() # Axios sends POST data in json rather than _Form-Encoded_. ids: List[int] = json.loads(request.body.decode('utf-8')) num_enrolled = Count('record', filter=Q(record__status=RecordStatus.ENROLLED)) is_enrolled = Count( 'record', filter=(Q(record__status=RecordStatus.ENROLLED, record__student_id=student.pk))) is_enqueued = Count( 'record', filter=(Q(record__status=RecordStatus.QUEUED, record__student_id=student.pk))) groups_from_ids = Group.objects.filter(pk__in=ids) groups_enrolled_or_enqueued = Group.objects.filter( course__semester=semester, record__status__in=[RecordStatus.QUEUED, RecordStatus.ENROLLED], record__student=student) groups_all = groups_from_ids | groups_enrolled_or_enqueued groups = groups_all.annotate(num_enrolled=num_enrolled).annotate( is_enrolled=is_enrolled).annotate(is_enqueued=is_enqueued).select_related( 'course', 'teacher', 'course__semester', 'teacher__user').prefetch_related( 'term', 'term__classrooms', 'guaranteed_spots', 'guaranteed_spots__role') can_enqueue_dict = Record.can_enqueue_groups(student, groups) can_dequeue_dict = Record.can_dequeue_groups(student, groups) for group in groups: group.can_enqueue = can_enqueue_dict.get(group.pk) group.can_dequeue = can_dequeue_dict.get(group.pk) group.is_enqueued = bool(group.is_enqueued) group.is_enrolled = bool(group.is_enrolled) group_dicts = build_group_list(groups) return JsonResponse(group_dicts, safe=False)