Django REST framework文件上传场景下serializer字段在validated_data丢失
问题原因
MultiPartParser解析multipart/form-data请求时,所有表单字段默认以字符串或二进制格式返回,无法自动转换为Python列表类型:- 若前端将
plugins序列化为JSON字符串提交,ListSerializer会因类型不匹配丢弃该字段(因你设置了required=False,校验不会抛出错误) - 若前端以
plugins[]为参数名提交多值数组,DRF默认不会自动聚合该类参数为列表,ListSerializer同样识别不到对应值
- 若前端将
- 新增
JSONParser无效的原因是:JSONParser仅处理Content-Type: application/json的请求,和MultiPartParser的处理范围完全独立,不会对multipart/form-data请求生效。
修复方案
方案1:自定义字段适配JSON字符串格式数组
如果前端选择将plugins序列化为JSON字符串提交,自定义列表字段自动解析JSON内容:
import json from rest_framework import serializers class JSONListField(serializers.Field): def __init__(self, child=None, **kwargs): self.child = child super().__init__(**kwargs) def to_internal_value(self, data): # 本身就是列表直接返回 if isinstance(data, list): res = data else: # 解析JSON字符串为列表 try: res = json.loads(data) except (json.JSONDecodeError, TypeError): raise serializers.ValidationError("需为合法的JSON列表格式") # 用child字段校验每个元素 if self.child: res = [self.child.to_internal_value(item) for item in res] return res def to_representation(self, value): return value
修改序列化器的plugins字段定义:
class CreationSerializer(serializers.ModelSerializer, FileUploadSerializer): plugins = JSONListField( child=serializers.CharField(), required=False, write_only=True) class Meta: fields = ['plugins'] + FileUploadSerializer.Meta.fields model = Company def create(self, validated_data): print(validated_data)
方案2:适配plugins[]多参数提交格式
如果前端以plugins[]为参数名提交多个值,在视图层提前处理请求参数:
@swagger_auto_schema(request_body=CreationSerializer(), responses={201: CreationSerializer()}, operation_id='the_post') def create(self, request, *args, **kwargs): # 聚合[]后缀的数组参数 if 'plugins[]' in request.data: request.data['plugins'] = request.data.pop('plugins[]') return super().create(request, *args, **kwargs)
排查小技巧:临时把
plugins字段的required属性改为True,提交请求会返回明确的字段校验错误信息,可快速确认字段被丢弃的具体原因。
内容的提问来源于stack exchange,提问作者creyD
相关产品推荐
相关产品推荐

