Reputation: 1572
I am want to be able to POST an entry to a ManyToManyField (ImageTag) one by one. I am using extra actions to make a nested endpoint under an Image.
I want to be able to POST an entry one POST at a time.
localhost:8000/my_app/images/IMG_123/image_tags/
I want to override the create method on the Serializer to do this. But the problem is its not getting called. Why?
This is my source code:
#models.py
class ImageTag(models.Model):
name = models.CharField()
description = models.CharField()
class Image(models.Model):
image_id = models.CharField(unique=True)
image_tags = models.ManyToManyField(ImageTag, blank=True)
...
#serializers.py
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = Image
fields = '__all__'
class ImageTagSerializer(serializers.ModelSerializer):
image_tags = serializers.StringRelatedField(many=True)
class Meta:
model = Image
fields = ('image_tags',)
def to_internal_value(self, data):
return data
def create(self, validated_data):
print("GOTHERE")
print("VALI", validated_data)
return validated_data
#views.py
class ImageExtraAction(viewsets.ModelViewSet):
@action(detail=True, methods=['get', 'post', 'delete'])
def image_tags(self, request, capture_id=None):
capture = self.get_object()
serializer = ImageTagSerializer(capture, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ImageTagViewSet(ImageExtraAction, viewsets.ModelViewSet):
queryset = Image.objects.all()
serializer_class = ImageSerializer
lookup_field = 'image_id'
...
#urls.py
router.register(r'images', ImageTagViewSet, basename='image')
Upvotes: 1
Views: 2942
Reputation: 76
The .create()
method is not called because you are not creating, rather updating an instance. To create an instance use:
serializer = ImageTagSerializer(data=request.data)
Upvotes: 1
Reputation: 3784
You try to put everything in your @action()
function, as if it was a new viewsets.ModelViewSet
. It's not working that way.
If you want to have all the mixins
of viewsets.ModelViewSet
, you have to create a separate ModelViewSet
, or reimplement all methods in your action (see, in your image_tags()
, the HTTP method is not even used)
Upvotes: 1
Reputation: 88519
Because you are passing the instance too while initializing the serializer.
serializer = ImageTagSerializer(capture, data=request.data)
Here, the capture
is the model instance, at that time DRF thinks it is an update operation hence, DRF uses the update(...)
method of the serializer.
Upvotes: 4