Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update course members sections #41

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions app/serializers/course_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from app.serializers.attribute import AttributeResponseSerializer
from app.serializers.relationship import RelationshipSerializer
from app.serializers.section import SectionSerializer
from app.models.section import Section


class CourseMemberSerializer(serializers.ModelSerializer):
Expand All @@ -21,3 +22,25 @@ class CourseMemberSerializer(serializers.ModelSerializer):
class Meta:
model = CourseMember
fields = "__all__"


class UpdateStudentSectionsRequest(serializers.Serializer):
sections = serializers.ListField(
child=serializers.IntegerField(),
required=True,
error_messages={
"required": "Sections is required.",
},
)

def validate_sections(self, value):
course = self.context.get("course")
sections_passed_in = set(value)
course_sections_ids = Section.objects.filter(
course=course, id__in=sections_passed_in
)
if len(sections_passed_in) != course_sections_ids.count():
raise serializers.ValidationError(
"One or more sections do not exist or are not part of the course."
)
return value
61 changes: 59 additions & 2 deletions app/views/course_member.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
from rest_framework import viewsets

from app.models.course_member import CourseMember
from app.models.course_member import CourseMember, UserRole
from app.paginators.pagination import ExamplePagination
from app.models.section import Section
from app.filters.course_member import FilterStudents
from app.serializers.course_member import CourseMemberSerializer
from app.serializers.course_member import (
CourseMemberSerializer,
UpdateStudentSectionsRequest,
)

from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework import status

from django.db import transaction
from django.core.exceptions import ValidationError
from rest_framework.exceptions import APIException


class CourseMemberViewSet(viewsets.ModelViewSet):
Expand All @@ -30,3 +40,50 @@ def get_students_by_course(self, request, course=None, *args, **kwargs):
else:
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

@action(detail=True, methods=["put"], url_path="update-sections")
@transaction.atomic
def update_sections(self, request, *args, **kwargs):
try:
course_member = self.get_object()

if course_member.role != UserRole.STUDENT:
return Response(
{
"errors": {
"message": "Only students can be assigned to sections."
}
},
status=status.HTTP_400_BAD_REQUEST,
)

request_body_serializer = UpdateStudentSectionsRequest(
instance=course_member,
data=request.data,
context={"course": course_member.course},
)
if request_body_serializer.is_valid(raise_exception=True):
section_ids = request_body_serializer._validated_data.get("sections")
proposed_sections_update = Section.objects.filter(
id__in=section_ids, course=course_member.course
)
course_member.sections.set(proposed_sections_update)
course_member.save()
response_course_member_serializer = self.get_serializer(course_member)
return Response(response_course_member_serializer.data)

except Exception as exc:
errors = []
if isinstance(exc, APIException):
if isinstance(exc.detail, dict):
for field, error_list in exc.detail.items():
for error in error_list:
errors.append({"message": str(error)})
else:
errors.append({"message": exc.detail})
if isinstance(exc, ValidationError):
for field, error_list in exc.detail.items():
for error in error_list:
errors.append({"message": str(error)})
response = Response({"errors": errors}, status=status.HTTP_400_BAD_REQUEST)
return response
Loading