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

Django Rest Framework使用登录令牌无需pk调用PUT接口更新User模型头像

问题根因

你使用的ModelViewSet默认的PUT方法对应带资源ID的详情路由(格式为/upload/<用户pk>/),而你请求的/upload/是列表路由,默认仅支持GET(查列表)、POST(创建资源)方法,所以直接请求/upload/的PUT会返回405方法不允许。


方案1:自定义非详情类action(更推荐,逻辑清晰)

直接在视图类中新增一个不需要传pk的自定义action,专门处理当前登录用户的头像更新:
修改views.py:

from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser
from rest_framework.permissions import IsAuthenticated
from . import serializers
from django.contrib.auth import get_user_model

User = get_user_model()

class UploadViewset(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = serializers.ImageUploadSerializer
    parser_classes = [MultiPartParser]
    # 确保只有登录用户可访问
    permission_classes = [IsAuthenticated]
    
    # 自定义action,detail=False表示不需要资源id,请求方法设为put
    @action(methods=['put'], detail=False, url_path='avatar')
    def update_avatar(self, request):
        # 直接获取当前登录用户
        user = request.user
        # partial=True支持局部更新,不用传用户模型的所有字段
        serializer = self.get_serializer(user, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

修改后请求地址变为/upload/avatar/,PUT请求该地址即可直接更新当前登录用户的头像,无需传任何pk参数。


方案2:重写get_object方法,适配原有路由

如果你不想修改请求地址,要继续用/upload/作为PUT接口地址,可以重写视图的核心方法适配逻辑:
修改views.py:

from rest_framework import viewsets
from rest_framework.parsers import MultiPartParser
from rest_framework.permissions import IsAuthenticated
from . import serializers
from django.contrib.auth import get_user_model

User = get_user_model()

class UploadViewset(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = serializers.ImageUploadSerializer
    parser_classes = [MultiPartParser]
    permission_classes = [IsAuthenticated]
    
    # 固定返回当前登录用户,忽略url中的pk参数
    def get_object(self):
        return self.request.user
    
    # 让列表路由支持PUT方法
    def get_http_method_names(self):
        if self.action == 'list':
            return ['put']
        return super().get_http_method_names()
    
    # 把列表路由的PUT请求绑定到默认更新逻辑
    def list(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

修改后直接用PUT请求原有/upload/地址即可完成更新。


注意事项

如果需要返回头像的可访问外链,需确保Django配置了正确的媒体资源路由,序列化器无需额外修改,DRF会自动返回资源的相对/绝对路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:42:01