Django REST文件上传报错:'OrderedDict'无'Doc'属性求助
解决Django REST Framework POST接口/docs/路径500错误:'OrderedDict' object has no attribute 'Doc'
问题定位
报错触发于/docs/路径,说明是API文档生成工具(如DRF自带文档、drf-yasg)解析视图逻辑时的异常,而非接口实际调用的业务错误。核心矛盾在于代码中序列化器数据使用不规范,导致文档工具误将序列化后的数据结构当作模型实例处理。
代码问题分析
- 混用
serializer.data与validated_data:serializer.data是验证后数据经过序列化输出的OrderedDict,而你创建模型实例时,部分字段用serializer.data.get(),Doc字段用validated_data.get()。文档工具解析时可能误将serializer.data视为模型实例,尝试通过属性访问(如.Doc)而非键取值,触发属性不存在的错误。 try-except语法错误:代码中Except应为小写except,语法错误会加剧文档解析时的异常抛出。- 序列化器字段配置缺失:未提供
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): # 你的视图逻辑
验证修复
- 重新执行
python manage.py makemigrations和migrate确认模型同步 - 启动服务后访问
/docs/,检查500错误是否消失 - 上传文件测试POST接口,验证业务功能正常
内容的提问来源于stack exchange,提问作者d44rte
相关产品推荐
相关产品推荐

