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

Django REST文件上传报错:'OrderedDict'无'Doc'属性求助

解决Django REST Framework POST接口/docs/路径500错误:'OrderedDict' object has no attribute 'Doc'

问题定位

报错触发于/docs/路径,说明是API文档生成工具(如DRF自带文档、drf-yasg)解析视图逻辑时的异常,而非接口实际调用的业务错误。核心矛盾在于代码中序列化器数据使用不规范,导致文档工具误将序列化后的数据结构当作模型实例处理。

代码问题分析

  1. 混用serializer.data与validated_data:
    serializer.data是验证后数据经过序列化输出的OrderedDict,而你创建模型实例时,部分字段用serializer.data.get(),Doc字段用validated_data.get()。文档工具解析时可能误将serializer.data视为模型实例,尝试通过属性访问(如.Doc)而非键取值,触发属性不存在的错误。
  2. try-except语法错误:代码中Except应为小写except,语法错误会加剧文档解析时的异常抛出。
  3. 序列化器字段配置缺失:未提供DocumentSerializer代码,但如果Doc字段未正确配置(如未用FileField处理上传文件),文档生成时无法解析文件类型,引发数据结构冲突。

修复步骤

1. 统一使用validated_data创建实例

is_valid()验证通过后,validated_data是经过校验的原始数据,比serializer.data更可靠,且避免文档解析时的类型混淆:

def post(self, request, *args, **kwargs):
    serializer = DocumentSerializer(data=request.data)
    try:
        serializer.is_valid(raise_exception=True)
        # 全部改用validated_data获取字段值
        new_document = Documents.objects.create(
            TipoDoc=serializer.validated_data.get("TipoDoc"),
            DataInsert=serializer.validated_data.get("DataInsert"),
            DataInizio=serializer.validated_data.get("DataInizio"),
            DataFine=serializer.validated_data.get("DataFine"),
            CompanyID=serializer.validated_data.get("CompanyID"),
            Doc=serializer.validated_data.get("Doc").read()
        )
        # 补充返回逻辑,示例:
        # return Response(DocumentSerializer(new_document).data, status=status.HTTP_201_CREATED)
    except Exception as e:
        # 替换为实际异常处理逻辑
        return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

2. 修正DocumentSerializer的Doc字段配置

确保序列化器正确处理上传文件,示例如下:

from rest_framework import serializers
from .models import Documents

class DocumentSerializer(serializers.ModelSerializer):
    # 用FileField处理上传文件,write_only=True避免序列化时返回二进制数据
    Doc = serializers.FileField(write_only=True)

    class Meta:
        model = Documents
        fields = ["TipoDoc", "DataInsert", "DataInizio", "DataFine", "CompanyID", "Doc"]

3. 避免文档生成时触发文件读取逻辑(可选)

如果使用drf-yasg等文档工具,可通过装饰器指定请求示例,避免工具模拟请求时执行文件读取:

from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi

class YourDocumentView(APIView):
    @swagger_auto_schema(
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                "TipoDoc": openapi.Schema(type=openapi.TYPE_STRING),
                "DataInsert": openapi.Schema(type=openapi.TYPE_STRING),
                "DataInizio": openapi.Schema(type=openapi.TYPE_STRING),
                "DataFine": openapi.Schema(type=openapi.TYPE_STRING),
                "CompanyID": openapi.Schema(type=openapi.TYPE_STRING),
                "Doc": openapi.Schema(type=openapi.TYPE_FILE),
            }
        )
    )
    def post(self, request, *args, **kwargs):
        # 你的视图逻辑

验证修复

  1. 重新执行python manage.py makemigrations和migrate确认模型同步
  2. 启动服务后访问/docs/,检查500错误是否消失
  3. 上传文件测试POST接口,验证业务功能正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 08:50:29