Django REST Framework保存图片时触发AttributeError错误求助
问题分析与修复方案
这个错误的核心原因是你把序列化器对象直接赋值给了模型的ImageField字段,这是完全错误的用法,导致Django试图处理一个不属于文件类型的对象,从而抛出_committed属性不存在的异常。
错误代码的问题点
你在视图里写了这行错误的代码:
user.profile.thumbnail = UserProfileSerializer(instance=user.profile, data=request.data)
user.profile.thumbnail是Django的ImageField,它需要接收的是上传的文件对象(来自request.FILES),而不是UserProfileSerializer的实例。当你把序列化器赋值给它之后,后续调用save()时,Django会尝试把这个序列化器对象当作文件来处理,自然找不到文件对象才有的_committed属性。
修复方案一:直接操作模型字段(最简洁)
直接从请求中获取上传的文件,赋值给模型字段并保存,最后用序列化器返回结果:
from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView from django.contrib.auth.models import User from .models import UserProfile from .serializers import UserProfileSerializer class CreateUpdateUserThumbnail(views.APIView): def post(self, request, **kwargs): # 先处理用户不存在的情况 try: user = User.objects.get(id=kwargs.get('user_id')) except User.DoesNotExist: return Response({"error": "指定用户不存在"}, status=status.HTTP_404_NOT_FOUND) # 从请求中获取上传的缩略图文件 thumbnail_file = request.FILES.get('thumbnail') if not thumbnail_file: return Response({"error": "请上传缩略图文件"}, status=status.HTTP_400_BAD_REQUEST) # 直接赋值并保存UserProfile实例 user.profile.thumbnail = thumbnail_file user.profile.save() # 用原序列化器返回更新后的用户资料 serializer = UserProfileSerializer(instance=user.profile) return Response(serializer.data, status=status.HTTP_201_CREATED)
修复方案二:使用专用序列化器处理更新(更规范)
如果你希望用序列化器来验证和处理文件上传,可以创建一个专门用于更新缩略图的序列化器(去掉thumbnail的read_only限制),然后在视图中使用它:
1. 新增专用序列化器
from rest_framework import serializers from .models import UserProfile class UserProfileThumbnailUpdateSerializer(serializers.ModelSerializer): class Meta: model = UserProfile fields = ('thumbnail',)
2. 修改视图代码
class CreateUpdateUserThumbnail(views.APIView): def post(self, request, **kwargs): try: user = User.objects.get(id=kwargs.get('user_id')) except User.DoesNotExist: return Response({"error": "指定用户不存在"}, status=status.HTTP_404_NOT_FOUND) # 使用专用序列化器处理文件上传 serializer = UserProfileThumbnailUpdateSerializer( instance=user.profile, data=request.data, partial=True # 允许部分更新 ) if serializer.is_valid(): serializer.save() # 用原序列化器返回完整的用户资料 response_serializer = UserProfileSerializer(instance=user.profile) return Response(response_serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
额外注意事项
- 确保前端发送请求时,使用
multipart/form-data格式来上传文件,否则后端无法从request.FILES中获取到文件。 - 原
UserProfileSerializer中thumbnail设为read_only是合理的,因为它只用于返回数据,不处理写入操作。
内容的提问来源于stack exchange,提问作者Melissa Stewart
相关产品推荐
相关产品推荐

