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)
问题根源
- 序列化器继承逻辑混乱:
ItemsSerializer同时继承object、ListSerializer和ModelSerializer,DRF中ListSerializer是专门处理批量数据的序列化器,不需要和ModelSerializer混合继承;且object放在继承列表首位会打乱Python的方法解析顺序,导致DRF的序列化逻辑失效。 - 返回值解析错误:
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
相关产品推荐
相关产品推荐

