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?

Peter Tseng
  • 1,294
  • 1
  • 12
  • 15

2 Answers2

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)
Peter Tseng
  • 1,294
  • 1
  • 12
  • 15
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()
Marcin Rapacz
  • 616
  • 8
  • 12
  • 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? – kdbanman Jul 14 '15 at 19:44
  • 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. – Marcin Rapacz Jul 16 '15 at 15:49