Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework create multiple objects

This is what I have so far.

My serializer:

class MySerializer(serializers.ModelSerializer):

     class Meta:
         model = MyModel
         fields = ('field_1', 'field_2', 'field_3')

My ModelViewset

class MyViewSet(ModelViewSet):

    serializer_class = MySerializer
    model = MyModel
    queryset = MyModel.objects.all().order_by('date_paid')

    def create(self, request, *args, **kwargs):
        many = True if isinstance(request.data, list) else False
        serializer = MySerializer(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)

My main concern is that when testing the endpoint to create multiple objects using the following payload, on the view the property request.data seem to be empty, as a result it returns errors of fields missing.

{
        'data': [
            {
                'type': 'MySerializer',
                'attributes': {
                    'field_1': 1,
                    'field_2': 0.05,
                    'field_3': 'abc'
                }
            },
            {
                'type': 'MySerializer',
                'attributes': {
                    'field_1': 1,
                    'field_2': 0.05,
                    'field_3': 'abc'
                }
            },
            {
                'type': 'MySerializer',
                'attributes': {
                    'field_1': 1,
                    'field_2': 0.05,
                    'field_3': 'abc'
                }
            }
        ]
    }

However when using a single object instance:

{
        'data': {
            'type': 'MySerializer',
            'attributes': {
                    'field_1': 1,
                    'field_2': 0.05,
                    'field_3': 'abc'
            }
        }
    }

It seeems to work just fine and the object is created.

I have tried several ways to accomodate the payload:

  • Placing the list of objects inside the attributes field.
  • Placing the list of instances directly on the data field but it returns either an object error, or and empty request.data

How am I supposed to send the data for multiple objects, is it even possible, I have read in many articles that just by placing many=True on the serializer instance is enough to accomplish this but I just cant't get the data from the request.

Any step that I missed or another workaround?

EDIT

Forgot to mention two things

  1. that I'm using django rest framework json api library, could that be the reason why the data is empty?
  2. I placed dictionaries since I'm testing the endpoints and I use json.dumps(payload) when sending data.
like image 372
erick.chali Avatar asked Sep 08 '25 09:09

erick.chali


1 Answers

Ok, I am actually surprised that the creation of a single object instance works, since the data doesn't seem to be in the correct format. When the many argument is used, the serializer expects a list but what you send is a json object.

This is what the JSON should like:

    [
        {

              "field_1": 1,
              "field_2": 0.05,
              "field_3': "abc"

        },
        {

              "field_1": 1,
              "field_2": 0.05,
              "field_3': "abc"

        },
        {

              "field_1": 1,
              "field_2": 0.05,
              "field_3': "abc"

        }
    ]

These are the points to note here:

  1. The JSON begins with a list
  2. The fields are directly in the body of each object - no type or attribute field, expect you implement the logic to parse that in your serializer
  3. JSON does not using single quotes but double quotes

Did you inpect the request.data to confirm that it is empty as you said? If so, then that is another issue altogether as it may be a parsing issue.

EDIT: Using JSON API

After a little digging in the Rest framework json api github page, I found this issue requesting support for bulk operations. Apparently, they added it in this pull request and you can see the correct format of multiple objects in the comments.

Yours should be like this:

{
"data": [
    {
        "type": "MySerializer",
        "attributes": {
            "field_1": 1,
            "field_2": 0.05,
            "field_3": "abc"
        }
    },
    {
        "type": "MySerializer",
        "attributes": {
            "field_1": 1,
            "field_2": 0.05,
            "field_3": "abc"
        }
    },
    {
        "type": "MySerializer",
        "attributes": {
            "field_1": 1,
            "field_2": 0.05,
            "field_3": "abc"
        }
    }
]

}

Most likely the parser couldn't parse the data in the format you provided and that's why your request.data is empty.

EDIT 2:

While the bulk operations feature has not been integrated in the json-api specs, the Django Rest JSON-API already added a special parser for it. So you'll have to add this parser JSONAPIBulkParser for it to work. Check out this comment in the PR

like image 101
Ken4scholars Avatar answered Sep 10 '25 16:09

Ken4scholars