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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:11:09