DRF bulk insert crashes on serializer.data: too many values to unpack (expected 2)

I have python 3.6 and my Django 2.2.28

I have two serializers and I use list_serializer_class for bulk inserts. I use viewset and in my viewset

@action(methods=['post'], detail=False, url_path='bulk')
    def bulk_create(self, request):
    serializer = self.get_serializer(data=items, many=True)
    .........
    self.perform_create(serializer)

The data is successfully inserted into the database but when I try to get the data from the serializer

headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

I get the error: too many values to unpack (expected 2) probably beucase it's trying to decode the data using the first serializer and not the list_serializer_class

These are my serializers:

    class ItemsSerializer(object, serializers.ListSerializer, serializers.ModelSerializer):
        name = serializers.CharField(source='name',
                                            max_length=90)
        def update(self, instance, validated_data):
            pass
        def create(self, validated_data):
            items = [Item(**item) for item in validated_data]
            return Item.objects.bulk_create(items)

    class Meta:
        model = ItemModel
        fields = ('id', 'name')
  
    class ItemSerializer(object, serializers.ModelSerializer):
        name = serializers.CharField(source='name',
                                            max_length=90)
        class Meta:
            list_serializer_class = ItemsSerializer
            model = ItemModel
            fields = ('id', 'name')

Trackeback

2024-02-22 14:56:19 Traceback (most recent call last):
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
2024-02-22 14:56:19     response = get_response(request)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
2024-02-22 14:56:19     response = self.process_exception_by_middleware(e, request)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
2024-02-22 14:56:19     response = wrapped_callback(request, *callback_args, **callback_kwargs)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/sentry_sdk/integrations/django/views.py", line 67, in sentry_wrapped_callback
2024-02-22 14:56:19     return callback(request, *args, **kwargs)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
2024-02-22 14:56:19     return view_func(*args, **kwargs)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/viewsets.py", line 125, in view
2024-02-22 14:56:19     return self.dispatch(request, *args, **kwargs)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/newrelic/hooks/component_djangorestframework.py", line 28, in _nr_wrapper_APIView_dispatch_
2024-02-22 14:56:19     return wrapped(*args, **kwargs)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py", line 509, in dispatch
2024-02-22 14:56:19     response = self.handle_exception(exc)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py", line 469, in handle_exception
2024-02-22 14:56:19     self.raise_uncaught_exception(exc)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
2024-02-22 14:56:19     raise exc
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py", line 506, in dispatch
2024-02-22 14:56:19     response = handler(request, *args, **kwargs)
2024-02-22 14:56:19   File "/project/cms/api/pages.py", line 176, in bulk_create
2024-02-22 14:56:19     print("serializer", serializer.data)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py", line 768, in data
2024-02-22 14:56:19     ret = super().data
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py", line 556, in data
2024-02-22 14:56:19     return ReturnDict(ret, serializer=self)
2024-02-22 14:56:19   File "/usr/local/lib/python3.6/site-packages/rest_framework/utils/serializer_helpers.py", line 18, in __init__
2024-02-22 14:56:19     super().__init__(*args, **kwargs)
2024-02-22 14:56:19 ValueError: too many values to unpack (expected 2)
    

My class ItemsSerializer extends both serializers.ListSerializer and serializers.ModelSerializer which is ok but when we try to access the property data in viewset we need the property from serializers.ModelSerializer so I've created a new property in ItemsSerializer named db_data with the code from serializers.ModelSerializer and now it works.

@property
def db_data(self):
    if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
        msg = (
            'When a serializer is passed a `data` keyword argument you '
            'must call `.is_valid()` before attempting to access the '
            'serialized `.data` representation.\n'
            'You should either call `.is_valid()` first, '
            'or access `.initial_data` instead.'
        )
        raise AssertionError(msg)

    if not hasattr(self, '_data'):
        if self.instance is not None and not getattr(self, '_errors', None):
            self._data = self.to_representation(self.instance)
        elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
            self._data = self.to_representation(self.validated_data)
        else:
            self._data = self.get_initial()
    return self._data

And I'm returning

return Response(serializer.db_data, status=status.HTTP_201_CREATED, headers=headers)
Back to Top