Search code examples
djangodjango-rest-frameworkdjango-ormdjango-rest-viewsets

How to save a modelSerializer that has relations? - django


I want to save a sent json data to db by django-rest-framework. the problem is, not saving the relation and returns error.

The bellow snippet is my models:

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='profile', on_delete=models.CASCADE)
    name = models.CharField(max_length=30)
    family = models.CharField(max_length=50)

class Klass(models.Model):
    title = models.CharField(max_length=50)
    description = models.CharField(max_length=500)
    teacher = models.ForeignKey(Profile, related_name='teacher', on_delete=models.CASCADE)

I use below serializer for serializing/deserializing the Klass model.

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ('pk', 'name', 'family')

class KlassSerializer(serializers.ModelSerializer):
    teacher = ProfileSerializer()        

    class Meta:
        model = Klass
        fields = ('id', 'title', 'description', 'teacher')

now when I prepare a JSON object and send it to the view, it returns error. the below is the view class:

class KlassView(APIView):
"""for SELECT, INSERT Queries"""

    def get(self, request, pk):
         # somthing

    @csrf_exempt
    def post(self,request, pk=None):
        """For Creating A Class"""
        serializer = KlassSerializer(data=request.data)
        if serializer.is_valid():
            teacher = ProfileSerializer(request.data['teacher']['pk'])
            serializer.teacher = teacher.data            
            serializer.save()
            return Response({'data': serializer.data})
        else:
            return Response({'data': serializer.errors})

and the error is:

The .create() method does not support writable nested fields by default. Write an explicit .create() method for serializer mainp.serializers.KlassSerializer, or set read_only=True on nested serializer fields.

How can I save relation in KlassSerializer in order to save to db?


Solution

  • At first change your serializer like below:

    class KlassSerializer(serializers.ModelSerializer):
        # teacher = ProfileSerializer() # No need to this!
    
        class Meta:
            model = Klass
            # fields = ('id', 'title', 'description', 'teacher')
            fields = ('id', 'title', 'description') # Omit teacher
    

    Then get profile from requested user and pass it to your serializer:

        def post(self,request, pk=None):
        """For Creating A Class"""
        serializer = KlassSerializer(data=request.data)
        if serializer.is_valid():
            teacher = ProfileSerializer(request.data['teacher']['pk'])
            serializer.teacher = teacher.data            
            serializer.save(teacher=request.user.profile) # Retrieve teacher and stroe 
            return Response({'data': serializer.data})
        else:
            return Response({'data': serializer.errors})