bulk_create using ListCreateAPIView and ListSerializer


What is the difference between the above two methods?

I don’t understand how they work, I did try googling, documentation, StackOverflow, medium articles but I don’t understand the working.

Does ListCreateAPIView hit the create method as the length of the list? How to override that?
ListSerializer, I don’t get this at all. So I gotta have a parent list serializer and child model serializer.

Where do I add the validations in each of these methods? And what if I want to override the fields or save extra information.

Basically, I am trying to create an API endpoint for bulk-creating users. That means apart from just the validations, I need to set the password for each user being created in the backend. How do I save it that way?

When I tried using the ListCreateAPIView, it kept throwing me the error ListSerializer is not iterable even after I set many = True.

Does ListCreateAPI works with just the model serializer or do I need to set the class to a ListSerializer class?

And, when I followed this medium article on bulk creating using ListSerializer, it kept telling me something like "JSON parse error – Expecting ‘,’ delimiter: line 4 column 20 (char 72)"

I seriously don’t get the working of both ListSerializer and ListCreateAPIView.

Any help would be highly appreciated. I am a newbie to this rest API thingy. Thanks.

My code is just basic


class BulkCreateUsersListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        users = [UserModel(**item) for item in validated_data]
        return UserModel.objects.bulk_create(users)

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = ...
        fields = ...
        list_serializer_class = BulkCreateUserListSerializers #commented when I tried using the ListCreateAPIView


class CreateBulkUsersAPIView(ListCreateAPIView):
    serializer_class = UserSerializer
    queryset = UserModel.objects.all()

    def get_serializer(self, *args, **kwargs):
        """ if an array is passed, set serializer to many """
        if isinstance(kwargs.get('data', {}), list):
            kwargs['many'] = True
        return super(CreateBulkUsersAPIView, self).get_serializer(*args, **kwargs)

—-Edit 1—-
Traceback for "ListSerializer object is not iterable"

Template error:
In template C:\Users\Documents\Django Projects\startup\env\lib\site-packages\rest_framework\templates\rest_framework\horizontal\form.html, error at line 2
   'ListSerializer' object is not iterable
   1 : {% load rest_framework %}
   2 :  {% for field in form %} 
   3 :   {% if not field.read_only %}
   4 :     {% render_field field style=style %}
   5 :   {% endif %}
   6 : {% endfor %}


You had a lot of questions so I will choose one that will probably solve most of your problems:

ListCreateApiView is for adding the functionality to list objects via get and create objects via post to your view.

The naming of ListCreateApiView doesn’t mean that you can create objects using a list (although the confusion is understandable). You can still support that though, but you need to write your own .create() method in the view like so:

class CreateBulkUsersAPIView(ListCreateAPIView):
    serializer_class = UserSerializer
    queryset = UserModel.objects.all()

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data, many=True)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

The only difference with the default create is get_serializer needs to be called with many=True to support creating a list of objects.

Answered By – Brian Destura

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published