Skip to content

Commit fa4374b

Browse files
Academics improvement
- added option to filter marks and attendance by GET params - made academics models primary keys uneditable - added subject semester and student current_sem validation to marks - added branch names metadata view and route, for form choices
1 parent abc7ca9 commit fa4374b

File tree

3 files changed

+63
-6
lines changed

3 files changed

+63
-6
lines changed

api/academics/models.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.core.validators import MinValueValidator, MaxValueValidator
55

66
class Branch(models.Model):
7-
code = models.CharField(primary_key=True, max_length=10)
7+
code = models.CharField(primary_key=True, max_length=10, editable=False)
88
name = models.CharField(max_length=100)
99
max_sems = models.IntegerField(default=8)
1010

@@ -15,10 +15,10 @@ def __str__(self):
1515
return self.name
1616

1717
class Subject(models.Model):
18-
code = models.CharField(max_length=10, primary_key=True)
18+
code = models.CharField(max_length=10, primary_key=True, editable=False)
1919
name = models.CharField(max_length=100)
2020
branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
21-
semester = models.IntegerField(default=8)
21+
semester = models.IntegerField()
2222
credits = models.IntegerField()
2323

2424
def __str__(self):
@@ -82,6 +82,9 @@ def clean(self) -> None:
8282
if marks[1] > total[1]:
8383
errors[marks[0]] = f'Marks cannot be greater than total marks: {total[1]}.'
8484

85+
if self.subject.semester > self.student.current_sem:
86+
errors['subject'] = f"Student current semester is {self.student.current_sem} but subject semester is {self.subject.semester}."
87+
8588
if errors:
8689
raise ValidationError(errors)
8790

api/academics/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
from academics.views import MarksViewSet, AttendanceViewSet
1+
from academics.views import MarksViewSet, AttendanceViewSet, get_branch_names
22

33
from django.urls import path
44

55
urlpatterns = [
6+
path('metadata/branches', get_branch_names, name='get_branch_names'),
67
path('marks/', MarksViewSet.as_view({
78
'get': 'list',
89
'post': 'create'

api/academics/views.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,47 @@
1-
from rest_framework import viewsets
2-
from academics.models import Marks, Attendance
1+
from rest_framework.decorators import api_view
2+
from rest_framework import viewsets, status
3+
from academics.models import Marks, Attendance, Branch
34
from academics.serializers import MarksSerializer, AttendanceSerializer
5+
from rest_framework.response import Response
46
from django.shortcuts import get_object_or_404
57
from core.permissions import isAdmin, isStaff, isOwner
68

79

10+
@api_view(['GET'])
11+
def get_branch_names(request):
12+
branches = Branch.objects.all()
13+
branches = [(branch.code, branch.name) for branch in branches]
14+
return Response(branches, status.HTTP_200_OK)
15+
16+
817
class MarksViewSet(viewsets.ModelViewSet):
918
queryset = Marks.objects.all()
1019
serializer_class = MarksSerializer
1120
lookup_fields = ('student_id', 'subject_id')
1221

1322

23+
def list(self, request, *args, **kwargs):
24+
serializer = self.get_serializer(data=request.GET, partial=True)
25+
26+
if serializer.is_valid():
27+
student = serializer.validated_data.get('student', {}).get('user', {}).get('id')
28+
subject = serializer.validated_data.get('subject', {}).get('code')
29+
30+
queryset = self.filter_queryset(self.get_queryset())
31+
if student: queryset = queryset.filter(student=student)
32+
if subject: queryset = queryset.filter(subject=subject)
33+
34+
page = self.paginate_queryset(queryset)
35+
if page is not None:
36+
serializer = self.get_serializer(page, many=True)
37+
return self.get_paginated_response(serializer.data)
38+
39+
serializer = self.get_serializer(queryset, many=True)
40+
return Response(serializer.data)
41+
42+
else: return super().list(request, *args, **kwargs)
43+
44+
1445
def get_object(self):
1546
queryset = self.filter_queryset(self.get_queryset())
1647

@@ -31,6 +62,28 @@ class AttendanceViewSet(viewsets.ModelViewSet):
3162
lookup_fields = ('student_id', 'subject_id')
3263

3364

65+
def list(self, request, *args, **kwargs):
66+
serializer = self.get_serializer(data=request.GET, partial=True)
67+
68+
if serializer.is_valid():
69+
student = serializer.validated_data.get('student', {}).get('user', {}).get('id')
70+
subject = serializer.validated_data.get('subject', {}).get('code')
71+
72+
queryset = self.filter_queryset(self.get_queryset())
73+
if student: queryset = queryset.filter(student=student)
74+
if subject: queryset = queryset.filter(subject=subject)
75+
76+
page = self.paginate_queryset(queryset)
77+
if page is not None:
78+
serializer = self.get_serializer(page, many=True)
79+
return self.get_paginated_response(serializer.data)
80+
81+
serializer = self.get_serializer(queryset, many=True)
82+
return Response(serializer.data)
83+
84+
else: return super().list(request, *args, **kwargs)
85+
86+
3487
def get_object(self):
3588
queryset = self.filter_queryset(self.get_queryset())
3689

0 commit comments

Comments
 (0)