How to use nested serializers with Django rest mixins

Viewed 144

I'm trying to implement CRUD operation in Django-REST framework with multiple models. The goal is to perform CRUD operation ron multiple table when the API call is made.

I use mixins from REST framework https://www.django-rest-framework.org/api-guide/generic-views/#mixins

I have found some relevant examples but still, my serializer is only returning the fields from the Student model for CRUDoperation. I'm not able to see the Course models field in REst api ui.

PROBLEM I can't get the fields from Homework and Course models.

How to display Data from two model without creating new model in Django?

use of mixins class defined in Django rest framework

models.py

class Student(models.Model):
    student_id = models.UUIDField(default=uuid.uuid4, unique=True,
                      primary_key=True, editable=False)
    firstName = models.CharField(max_length=20)
    age = models.IntegerField(default=18)

   

class Course(models.Model):
    student_id = models.ForeignKey(Student, on_delete=models.CASCADE)
    courseName = models.CharField(max_length=20)
    courseYear = models.IntegerField(default=2021)
    student = models.ManyToManyField(Student, related_name='courses')


class Homework(models.Model):
    student_id = models.ForeignKey(Student, on_delete=models.CASCADE)

    hwName = models.CharField(max_length=20)
    hwPossScore = models.IntegerField(default=100)
    course = models.ForeignKey(Course, related_name='homeworks', on_delete=models.CASCADE, null=True, blank=True)
    students = models.ManyToManyField(Student)

Serializers.py

class StudentSerializer(serializers.ModelSerializer):
  
    class Meta:
        model = Student
        fields = "__all__"


class HomeworkSerializer(serializers.ModelSerializer):
   
    class Meta:
        model = Homework
        fields = __all__


class CourseSerializer(serializers.ModelSerializer):
   
    class Meta:
        model = Course
        fields = "__all__"
###I combine both Student and Course into one
class All_Serializer(serializers.ModelSerializer):
    
    students = serializers.SerializerMethodField()
    homeworks = serializers.SerializerMethodField()
    courses = serializers.SerializerMethodField()
    
    def get_students(self, obj):
        students = obj.student_set.all()
        serializer = StudentSerializer(students, many=True)
        return serializer.data

    def get_homeworks(self, obj):
        homeworks = obj.homework_set.all()
        serializer = HomeworkSerializer(homeworks, many=True, read_only=True)  
        return serializer.data

    def get_courses(self, obj):
        courses = obj.courses_set.all()
        serializer = CourseSerializer(courses, many=True, read_only=True)  
        return serializer.data

    class Meta:
        model = Student
        fields = ('student_id','firstName','age','homeworks','courses')
   

views.py

 class Main_mixins(generics.GenericAPIView, 
                                mixins.ListModelMixin, 
                                mixins.CreateModelMixin,
                                mixins.RetrieveModelMixin,
                                mixins.UpdateModelMixin,
                                mixins.DestroyModelMixin):
    serializer_class = All_Serializer
    queryset = Student.objects.all()
    lookup_field = 'student_id'

    def get(self, request, student_id=None):
        if student_id:
           return self.retrieve(request, student_id)
        else:
            return self.list(request)
    
    def post(self, request):
        return self.create(request)
    
    def perform_create(self, serializer):
        serializer.save()
    
    
    def put(self, request, student_id=None):
        return self.update(request, student_id=None, homeworks, courses)

thanks for your help in advance!

1 Answers

Not really sure what you trying to do.

The model of course and homework belongs to one student or to have many of the student? Pardon me if I miss-understanding the purpose of your implementation.

But if you want your student queryset include a course and homework fields. You may try the code below.

models.py

class Student(models.Model):
   student_id = models.UUIDField(default=uuid.uuid4, unique=True,
                     primary_key=True, editable=False)
   firstName = models.CharField(max_length=20)
   age = models.IntegerField(default=18)

   def get_course_set(self):
      return Course.objects.filter(student_id=self)

   def get_homework_set(self):
      return Homework.objects.filter(student_id=self)


class Course(models.Model):
    ...


class Homework(models.Model):
    ...
    

serializers.py

class HomeworkSerializer(serializers.ModelSerializer):
   
    class Meta:
        model = Homework
        fields = __all__


class CourseSerializer(serializers.ModelSerializer):
   
    class Meta:
        model = Course
        fields = "__all__"


class StudentSerializer(serializers.ModelSerializer):
    course = CourseSerializer(source="get_course_set", many=True, read_only=True)
    homework = HomeworkSerializer(source="get_homework_set", many=True, read_only=True)
  
    class Meta:
        model = Student
        fields = "__all__"

# Remove All_Serializer
# class All_Serializer(serializers.ModelSerializer):
      ...

views.py


class Main_mixins(generics.GenericAPIView, 
                                mixins.ListModelMixin, 
                                mixins.CreateModelMixin,
                                mixins.RetrieveModelMixin,
                                mixins.UpdateModelMixin,
                                mixins.DestroyModelMixin):

    # Change from All_Serializer to StudentSerializer
    serializer_class = StudentSerializer
    queryset = Student.objects.all()
    lookup_field = 'student_id'

    ...
Related