10

I'm trying to make an api where you can create multiple objects with a single Post request using django rest framework. However, my serializer is providing an error which I don't understand. First off here's the a skeleton of my code

My Serializer:

class MyModelSerializer(serializers.ModelSerializer):
# override the constructor to always use the many flag
def __init__(self, *args, **kwargs):
    many = kwargs.pop('many', True)
    super(MyModelSerializer, self).__init__(many=many, *args, **kwargs)

class Meta:
    model = MyModel
    fields = ('field1', 'field2')

My List View

class MyModelListView(generics.ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    def post(self, request, *args, **kwargs):
        if request.DATA['batch']:
            json = request.DATA['batchData']
            stream = StringIO(json)
            data = JSONParser().parse(stream)
            request._data = data
        return super(CharacterDatumList, self).post(request, *args, **kwargs)

My ajax call

$.ajax({
    type: "POST",
    url: '/characterDatum/',
    data: {
        'batch' : true,
        'batchData' : '[{"field1": "x", "field2": "y", },{"field1": "a", "field2": "b"}]'
    },
    success: function(response) {
        console.log('success');
    },
    datatype: 'json'
});

However, in the django rest framework I get a serialization validation error at the line below

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.DATA, files=request.FILES)
        if serializer.is_valid(): # returns not valid

Does anyone know why this might be the case?

2 Answers 2

8

I found it! The serializer was not actually using the many option so I had to override the get_serializer method in MyModelListView

def get_serializer(self, instance=None, data=None,
                        files=None, many=True, partial=False):
        return super(MyModelListView, self).get_serializer(instance, data, files, many, partial)
Sign up to request clarification or add additional context in comments.

Comments

1

Here is what worked for me. I had to iterate over the list of items.

class ProportionViewSet(viewsets.ModelViewSet):
    queryset = Proportion.objects.all()
    serializer_class = ProportionSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data, many=True)
        serializer.is_valid(raise_exception=True)

        ###
        # First we need to iterate over the list o items
        ###

        for single_proportion in serializer.validated_data:
            # Try to get proportion from database for selected user
            try:
                proportions = Proportion.objects.get(user=self.request.user, category=single_proportion['category']['id'])
                proportions.some_property = "New value"
                proportions.save()
            # If it is not in the model, then we should create it
            except Proportion.DoesNotExist:
                proportion = Proportion(
                    category=Category.objects.get(id=single_proportion['category']['id']),
                    proportion_in_clicks=single_proportion['proportion_in_clicks'],
                    user=single_proportion['user']
                )
                proportion.save()

2 Comments

It's a little difficult to see how this is answers the question. Can you show why this addresses the problem in the question? Maybe by focusing on which part of your code is related to the problem?
The question was how to create many object with a single post request. Above code, thanks to option many = True allows you to create many objects with a single request. You can find posted data in serializer.validated_data and then interate over this list to create objects you want.

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.