Aniket Banyal
Aniket Banyal

Reputation: 452

Auto generated model field in DRF serializer

I have a model Classroom which has a field code that is generated automatically

from django.utils.crypto import get_random_string

class Classroom(models.Model):
    CODE_LEN = 16
    teacher = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    name = models.CharField(max_length=250)
    subject = models.CharField(max_length=50)
    code = models.CharField(max_length=CODE_LEN, unique=True)

    def save(self, *args, **kwargs):
        while True:
            self.code = get_random_string(length=16)
            if not Classroom.objects.filter(code=self.code).exists():
                break

        super().save(*args, **kwargs)

The serializer for Classroom is -

class ClassroomSerializer(serializers.ModelSerializer):
    class Meta:
        model = Classroom
        fields = ('teacher', 'name', 'subject', 'code')

This is the view for creating new Classroom -

class ListCreateClassroom(APIView):
    def get(self, request):
        classrooms = Classroom.objects.all()
        serializer = ClassroomSerializer(classrooms, many=True)
        return Response(serializer.data)

    def post(self, request):
        token = request.headers.get('Authorization').split()[1]
        token_obj = AccessToken.objects.get(token=token)
        teacher = token_obj.user.pk
        request.data.update({"teacher": teacher})

        serializer = ClassroomSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

When I send an api request to add new classroom, the request doesn't contain the code field because of which serializer.is_valid() throws error.

One way to solve it would be to create a code in the view and add it to the request.
But, is there a better way?

Upvotes: 0

Views: 208

Answers (1)

Hafnernuss
Hafnernuss

Reputation: 2827

Simply set the code field in the serializer to read_only=True:

class ClassroomSerializer(serializers.ModelSerializer):
  
  code = serializers.CharField(read_only=True)      

  class Meta:
    model = Classroom
    fields = ('teacher', 'name', 'subject', 'code')

Upvotes: 1

Related Questions