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

Django中run_validation移除QueryDict嵌套序列化字段的解决方法

问题:DRF序列化器run_validation移除嵌套字段dress_sizes

场景:使用自定义MultipartJsonParser处理Multipart/form-data请求(包含JSON数据和图片),序列化器中定义了嵌套字段dress_sizes = SizeSerializer(many=True, required=False),但经过run_validation后,该字段从验证数据中消失,导致create方法无法获取。

代码示例

序列化器代码

class CreateSerializer(ModelSerializer[Dress]):
    dress_sizes = SizeSerializer(many=True, required=False)

    def run_validation(self, data: Any = ...) -> Any | None:
        return super(CreateSerializer, self).run_validation(data)

    def validate(self, data):
        return super().validate(data)

自定义解析器代码

class MultipartJsonParser(MultiPartParser):
    def parse(self, stream, media_type=None, parser_context=None):
        result = super().parse(
            stream, media_type=media_type, parser_context=parser_context
        )
        data = {}

        for key, value in result.data.items():
            if type(value) != str:
                data[key] = value
                continue
            if "{" in value or "[" in value:
                try:
                    data[key] = json.loads(value)
                except ValueError:
                    data[key] = value
            else:
                data[key] = value
        qdict = QueryDict('', mutable=True)
        qdict.update(data)
        return DataAndFiles(qdict, result.files)

数据变化

  • run_validation前的请求数据:
< QueryDict: {
  'file_name': ['swimsuit.svg'],
  'dress_sizes': [
    [{
      'size': 'xs'
    }, {
      'size': 's'
    }, {
      'size': 'm'
    }, {
      'size': 'l'
    }, {
      'size': 'xl'
    }]
  ],
  'image': [ < TemporaryUploadedFile: swim.svg(image / svg + xml) > ]
} >
  • run_validation后的验证数据:
OrderedDict([('file_name', 'swimsuit.svg'), ('image', <
  TemporaryUploadedFile: swim.svg(image / svg + xml) > )])

原因分析

问题出在自定义解析器的最后一步:将处理后的data字典更新到QueryDict中时,QueryDict的update方法会把列表类型的值再次包裹一层列表。原本解析后的dress_sizes是一维数组[{...}, {...}],经过QueryDict处理后变成了嵌套列表[[{...}, {...}]],而DRF的嵌套序列化器SizeSerializer(many=True)只能识别一维列表,因此run_validation时无法匹配字段规则,直接丢弃了该字段。

解决方案

移除解析器中转换QueryDict的步骤,直接返回处理后的普通字典即可,DRF序列化器可以直接处理字典类型的输入:

修改后的解析器代码:

class MultipartJsonParser(MultiPartParser):
    def parse(self, stream, media_type=None, parser_context=None):
        result = super().parse(
            stream, media_type=media_type, parser_context=parser_context
        )
        data = {}

        for key, value in result.data.items():
            # 用isinstance替代type判断,更严谨
            if not isinstance(value, str):
                data[key] = value
                continue
            if "{" in value or "[" in value:
                try:
                    data[key] = json.loads(value)
                except ValueError:
                    data[key] = value
            else:
                data[key] = value
        # 直接返回普通字典,无需转换为QueryDict
        return DataAndFiles(data, result.files)

修改后,dress_sizes会以一维列表的形式传入序列化器,run_validation就能正确识别并保留该字段,后续的validate和create方法也能正常获取到数据。


内容的提问来源于stack exchange,提问作者Sardar Faisal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 20:25:30