You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF批量插入成功后获取serializer.data报错:too many values to unpack

问题详情

环境:Python 3.6、Django 2.2.28
用DRF的list_serializer_class实现批量插入,数据已成功写入数据库,但调用serializer.data时触发错误:ValueError: too many values to unpack (expected 2)。

相关代码

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)
    print("serializer", serializer.data)  # 触发错误的代码行

序列化器代码

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')

错误栈信息

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)
问题根源
  1. 序列化器继承逻辑混乱:ItemsSerializer同时继承object、ListSerializer和ModelSerializer,DRF中ListSerializer是专门处理批量数据的序列化器,不需要和ModelSerializer混合继承;且object放在继承列表首位会打乱Python的方法解析顺序,导致DRF的序列化逻辑失效。
  2. 返回值解析错误:bulk_create返回的是对象列表,但混乱的继承结构让序列化器无法正确解析该列表,触发了解包错误。
修复方案

调整序列化器结构,拆分批量和单对象序列化逻辑:

# 专门处理批量创建的ListSerializer
class ItemsListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        items = [ItemModel(**item) for item in validated_data]
        return ItemModel.objects.bulk_create(items)

# 单对象序列化器
class ItemSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='name', max_length=90)

    class Meta:
        model = ItemModel
        fields = ('id', 'name')
        # 指定批量场景使用的序列化器
        list_serializer_class = ItemsListSerializer

同时修正ViewSet中的接口,确保数据来源正确:

@action(methods=['post'], detail=False, url_path='bulk')
def bulk_create(self, request):
    serializer = self.get_serializer(data=request.data, many=True)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    return Response(serializer.data)
关键说明
  • ItemsListSerializer仅继承ListSerializer,专注处理批量创建逻辑,无需混入ModelSerializer。
  • 单对象序列化器通过Meta的list_serializer_class指定批量场景的序列化器,DRF会自动在传入many=True时切换使用。
  • 修正后bulk_create返回的对象列表能被正确序列化,避免解包错误。

内容的提问来源于stack exchange,提问作者Andrei Lupuleasa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 15:45:56