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

Django REST framework文件上传场景下serializer字段在validated_data丢失

问题原因

  1. MultiPartParser解析multipart/form-data请求时,所有表单字段默认以字符串或二进制格式返回,无法自动转换为Python列表类型:
    • 若前端将plugins序列化为JSON字符串提交,ListSerializer会因类型不匹配丢弃该字段(因你设置了required=False,校验不会抛出错误)
    • 若前端以plugins[]为参数名提交多值数组,DRF默认不会自动聚合该类参数为列表,ListSerializer同样识别不到对应值
  2. 新增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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 00:24:05