6

I have a very simple model and its related serializer and views:

class Page(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=255)
    pub_date = models.DateTimeField(default=timezone.now)

class PageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Page
        fields = ('user', 'title', 'pub_date')

class PageViewSet(viewsets.ModelViewSet):
    queryset = Page.objects.all()
    serializer_class = PageSerializer

Now I can post like this:

{
    "user": 1,
    "title": "Lorem ipsum"
}

This works fine. But I would like to post multiple objects like this:

[
    {
        "user": 1,
        "title": "Lorem ipsum one"
    },
    {
        "user": 1,
        "title": "Lorem ipsum two"
    }
]

But this gives me an error:

"non_field_errors": [

"Invalid data. Expected a dictionary, but got list."

]

So to accept multiple objects I modified the view as per the doc:

class PageViewSet(viewsets.ModelViewSet):
    queryset = Page.objects.all()
    serializer_class = PageSerializer(queryset, many=True)

But I am getting an error:

TypeError at /api/blog/pages/

'ListSerializer' object is not callable

What am I missing here?

2 Answers 2

12

You had it set up correctly before, the serializer_class should point to the class like this:

serializer_class = PageSerializer

You were right on the error, it doesn't like receiving multiple objects in the POST. One way to fix it would be to override the get_serializer method n the view, adding in many=True there.

Something like:

def get_serializer(self, *args, **kwargs):
    if "data" in kwargs:
        data = kwargs["data"]

        # check if many is required
        if isinstance(data, list):
            kwargs["many"] = True

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

To answer your question in the comments: isinstance() is a Python method to check the type of an object. In this case, it's a list when passing in multiple objects, so we just check what type data is and set many=true if it's a list.

DRF docs regarding get_serializer (under methods)

Python docs regarding isinstance

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

4 Comments

Woah... Thank you. I didn't show any docs on isinstance() method. Could you maybe point me where it is, or maybe elaborate how to use isinstance() please.
No problem, glad it helped. I've updated my answer to provide more info on that.
Thank you so much!
Sure thing! Glad I could help.
0

Other way to do this

def create(self, request, *args, **kwargs):
    many = True if isinstance(request.data, list) else False
    serializer = self.get_serializer(data=request.data, many=many)

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

Comments

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.