0

There seems to be a lot of documentation out there on this but none of it seems to work for me. I am trying to build an API View that creates one or many objects at the same time.

Something like passing in the following:

[
    {
        "response": "I have no favourites",
        "user": 1,
        "update": "64c5fe6f-cb65-493d-8ef4-126db0195c33",
        "question": "297b46b4-714b-4434-b4e6-668ff926b38e"
    },
    {
        "response": "Good",
        "user": 1,
        "update": "64c5fe6f-cb65-493d-8ef4-126db0195c33",
        "question": "13916052-690e-4638-bb7c-908c38dcd75e"
    }
]

My current Viewset

class FeedbackViewSet(viewsets.ModelViewSet):

    permission_classes = [AllowAny]
    queryset = Feedback.objects.all()
    serializer_class = FeedbackSerializer

and Serializer:

class ContributionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Contribution
        fields = '__all__'

I have tried setting FeedbackSerializer(many=True) but this then tells me its not callable. Further, I have tried a ListCreateAPIView but this tells me it expects a dictionary but not a list.

3
  • Hello, does this help you ? stackoverflow.com/a/16697324/13964753 Commented Apr 18, 2021 at 17:27
  • Unfortunately I had already seen this. When I follow this approach - I get the error 'Expected a dictionary but got a list' Commented Apr 18, 2021 at 17:31
  • Maybe your are searching for a bulk creation method ? Commented Apr 18, 2021 at 17:43

2 Answers 2

1

you have the correct idea with many=True. You just need to put it in the correct location... so in the ViewSet:

class FeedbackViewSet(viewsets.ModelViewSet):

    permission_classes = [AllowAny]
    queryset = Feedback.objects.all()
    serializer_class = FeedbackSerializer

    def get_serializer(self, *args, **kwargs):
        # add many=True if the data is of type list
        if isinstance(kwargs.get("data", {}), list):
            kwargs["many"] = True

        return super(FeedbackViewSet, self).get_serializer(*args, **kwargs)

There are other ways to achieve the same behaviour, but I think this is pretty clean!

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately seems to give me an error: 'ListSerializer' object is not iterable. It seemed to create the objects tho so guess the return is doing something odd.
I am looking into it
1

Override the create(...) method

from rest_framework.response import Response
from rest_framework import status


class FeedbackViewSet(viewsets.ModelViewSet):
    permission_classes = [AllowAny]
    queryset = Feedback.objects.all()
    serializer_class = FeedbackSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data, many=True) # not that `many=True` id mandatory since you are dealing with a list of of inputs
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            serializer.data,
            status=status.HTTP_201_CREATED,
            headers=headers
        )

2 Comments

This works! Thanks. However, only with multiple objects. Any idea how to make this dynamic to handle 1 or many?
Controll the many=True accordingly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.