Nested Serializer for prefect_related in Django Rest Framework

Question:

I’m trying to make a nested serializer with prefect_related but it doesn’t work, here’s my code:

models.py

from django.db import models


class Student(models.Model):
    phone = models.IntegerField(null=True)
    birth_date = models.DateField(null=True)
    user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, related_name="student")


class Course(models.Model):
    title = models.CharField(max_length=100, blank=True, default='')


class CourseEnroll(models.Model):
    course = models.ForeignKey(Course, on_delete=models.PROTECT, related_name='course_enroll')
    student = models.ForeignKey(Student, on_delete=models.PROTECT, related_name='student_enroll')

views.py

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet

from quiz.models import Course
from quiz.serializers import CourseSerializer


class CourseViewSet(mixins.CreateModelMixin,
                    mixins.ListModelMixin,
                    mixins.RetrieveModelMixin,
                    GenericViewSet):

    def get_queryset(self):
        queryset = Course.objects.prefetch_related("course_enroll").all()
        return queryset
    serializer_class = CourseSerializer

serializers.py

from rest_framework import serializers

from quiz.models import Course, CourseEnroll


class CourseEnrollSerializer(serializers.ModelSerializer):
    class Meta:
        model = CourseEnroll
        fields = ['id']


class CourseSerializer(serializers.ModelSerializer):
    student_enrolled = CourseEnrollSerializer(many=True, read_only=True)

    class Meta:
        model = Course
        fields = ['id', 'title', 'student_enrolled']

Here’s my repo:
https://github.com/congson95dev/regov-pop-quiz-backend-s-v1

Did I do something wrong here? Please help, thanks.

Asked By: fudu

||

Answers:

prefetch_related does not create a nested serialization. Rather it is used to cache the related model fields, so that when the queryset is executed, it does not make additional DB calls.

Here, you are using student_entrolled pointing to CourseEnrollSerializer, which won’t work because of wrong field name. It should be:

class CourseSerializer(serializers.ModelSerializer):
    course_enroll = CourseEnrollSerializer(many=True, read_only=True)

    class Meta:
        model = Course
        fields = ['id', 'title', 'course_enroll']
Answered By: ruddra