Reputation: 763
When I add a serializer for the ManyToMany Field, it displays the results on the REST API but when I post data then the serializer gives is_valid() as false. When I mention them as JSONFields, then the serializer is_valid() is True and the data gets saved, but upon viewing the api on localhost it gives the following error - 'Object of type 'ManyRelatedManager' is not JSON serializable'
class B(models.model):
name = models.CharField()
class A(models.model):
b = models.ManyToManyField(B)
class BSerializer(serializer.modelSerializer):
class Meta:
model=B
fields = '__all__'
class ASerializer(serializer.ModelSerializer):
b = BSerializer(many=true)
def save(self):
b_data = self.validated_data.pop('b')
a = A.objects.create(**validated_data)
b_instance = B.objects.get(name=b_data['name'])
a.add(b_instance)
This gives perfect results on the REST Framework UI when hit with http://localhost:8000/a/REST but when I hit the POST request on postman with the data {'b':[{'name':'foo'}]} the serializer fails to is_valid() function.
But when I change the code to this:
class ASerializer(serializer.ModelSerializer):
b = serializer.JSONField()
def save(self):
b_data = self.validated_data.pop('b')
a = A.objects.create(**validated_data)
b_instance = B.objects.get(name=b_data['name'])
a.add(b_instance)
The postman hit saves the data for A and then adds the b instance to it. It is seen when I see the data in python shell. But upon viewing it on the REST Framework UI, it gives the follwoing error: 'Object of type 'ManyRelatedManager' is not JSON serializable'
Upvotes: 2
Views: 1094
Reputation: 763
As answered by @Satendra I made 2 serializers but was receiving erros in viewset.
def create(self, request):
try:
serializer = self.get_serializer_class()
if serializer.is_valid():
serializer.save()
return Response({"status": "success"})
else:
return Response({"status": "failure", "reason": 'Serializer not valid'})
except Exception as e:
print('Error in viewset', e)
return Response({"status": "failure", "reason": e})
So just changed to this code and added a new line instantiating the serializer with data after calling the get_serializer_class and it works fine for both get and post request and using separate serializers for get and post
serializer = serializer(data=self.request.data)
Upvotes: 0
Reputation: 6865
You have to create two separate serializers
one for retrieval.
class A_RetriveSerializer(serializer.ModelSerializer):
b = BSerializer(many=true)
class Meta:
model = A
fields = '__all__'
and other for creating object.
class A_PostSerializer(serializer.ModelSerializer):
b = serializer.JSONField()
class Meta:
model = A
fields = ('b', )
def save(self):
b_data = self.validated_data.pop('b')
a = A.objects.create(**validated_data)
b_instance = B.objects.get(name=b_data['name'])
a.b.add(b_instance)
and in your view override get_serializer_class
method
def get_serializer_class(self):
if self.request.method == 'POST':
return A_PostSerializer
return A_RetriveSerializer
Upvotes: 1