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

React上传图片至Django后端及PUT请求更新图片失败求助

问题:PUT请求更新图片失败,始终返回旧图片

尝试向Django后端发起PUT请求更新用户头像,但每次返回的都是数据库中已存在的旧图片,新上传的图片并未完成更新,控制台显示的图片信息与实际上传的不一致。


相关代码

views.py

@api_view(['PUT'])
def UserPageCreateView(request, pk):

    if request.method == "PUT":
        page = UserPage.objects.get(id=pk)
        serializer = UserPageSerializer(instance=page, data=request.data, many=False, partial="True")
            
    if serializer.is_valid():
                
        serializer.save()

    return Response(serializer.data)

models.py

class UserPage(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    slug = models.SlugField()
    title = models.CharField(max_length=100, default="")
    description = models.TextField(max_length=100, default="")
    profile_photo = models.ImageField(upload_to="images", default="media/images/apple_atgqt1")
    

    def save(self, *args, **kwargs):
        self.slug = self.user.username
        super().save(*args, **kwargs)

    def __str__(self):
        return self.user.username

    def get_absolute_url(self):
        return reverse("page_detail", kwargs={"slug": self.slug})

serializers.py

class UserPageSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserPage
        fields = '__all__'

React Fetch请求代码

const PageUpdate = async (e) => {

    const response =  await fetch(`http://127.0.0.1:8000/page-create/${id}`,{
      method: "PUT",
      credentials: "include",
     headers: {
       
       "Content-Type": "multipart/form-data"
      },
      
      
      body:JSON.stringify({
        
        "profile_photo": profile_photo,
       
    })
    })

    let data = await response.json()
    console.log(data)
  }

图片选择模态框代码

<Modal.Body>
  <Form>
    <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
      <Form.Label>Email address</Form.Label>
      <Form.Control
        type="file"
        value={profile_photo}
        onChange={(e) => setProfilePhoto(e.target.value)}
        
      />
    </Form.Group>
    <Form.Group
      className="mb-3"
      controlId="exampleForm.ControlTextarea1"
    >
      
    </Form.Group>
    <Button variant="secondary" onClick={handleClose}>
    Cancel
  </Button>
  </Form>
</Modal.Body>

问题分析与修复方案

前端核心问题与修复

  1. 文件对象获取错误:e.target.value仅返回文件路径字符串,无法作为文件上传。需改为获取文件对象:
    onChange={(e) => setProfilePhoto(e.target.files[0])}
    
  2. 请求格式错误:不能用JSON.stringify处理文件上传,必须使用FormData封装数据,且无需手动设置Content-Type(浏览器会自动添加正确的边界标识):
    const PageUpdate = async (e) => {
      const formData = new FormData();
      formData.append('profile_photo', profile_photo);
    
      const response = await fetch(`http://127.0.0.1:8000/page-create/${id}`, {
        method: "PUT",
        credentials: "include",
        body: formData
      })
    
      let data = await response.json()
      console.log(data)
    }
    

后端核心问题与修复

  1. 视图逻辑漏洞:serializer定义在PUT判断块内,非PUT请求会导致未定义错误;partial参数需传布尔值True而非字符串"True"。
  2. 未处理序列化错误:需在验证失败时返回错误信息,便于排查问题。

修复后的views.py:

from rest_framework import status

@api_view(['PUT'])
def UserPageCreateView(request, pk):
    page = UserPage.objects.get(id=pk)
    serializer = UserPageSerializer(instance=page, data=request.data, many=False, partial=True)
    
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data)
    
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

额外配置检查

确保Django项目正确配置媒体文件:

  • 在settings.py中添加:
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    
  • 在根路由中添加媒体文件访问路由:
    from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        # 其他路由
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:48:23