Django中如何实现URL不携带ID的PUT请求操作
问题原因
DRF 默认的 ViewSet 路由绑定规则中,UpdateModelMixin 提供的update方法仅会被绑定到带资源唯一标识的detail路径(比如默认的/profile/<pk>/ 或者你指定lookup_field后的/profile/<username>/),不带标识的根路径(/profile/)默认只支持GET(对应list方法)和POST(对应create方法),所以你直接请求根路径的PUT会返回405方法不允许。
可行解决方法
方法1:手动绑定路由映射
无需修改现有视图逻辑,直接在urls.py中手动指定PUT请求和update方法的绑定关系即可:
from django.urls import path from .views import ProfileViewSet urlpatterns = [ path('profile/', ProfileViewSet.as_view({ 'get': 'list', 'put': 'update' # 手动将根路径的PUT请求绑定到update方法 })), ]
对应的视图中的update方法可以直接复用父类逻辑,不需要额外编写业务代码:
def update(self, request, *args, **kwargs): return super().update(request, *args, **kwargs)
方法2:用@action装饰器自定义端点
这是DRF更推荐的扩展方式,不需要修改默认路由规则,直接在视图中添加全局动作即可:
from rest_framework.decorators import action from rest_framework.response import Response class ProfileViewSet(mixins.ListModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet): serializer_class = UserProfileSerializer permission_classes = [IsAuthenticated] queryset = User.objects.all() def get_object(self): # IsAuthenticated权限已保证用户存在,不需要额外捕获NotFound return self.request.user # detail=False表示这是全局动作,不需要资源标识 @action(methods=['GET', 'PUT', 'PATCH'], detail=False, url_path='current') def current_profile(self, request, *args, **kwargs): instance = self.get_object() if request.method == 'GET': serializer = self.get_serializer(instance) return Response(serializer.data) # 处理PUT/PATCH更新 partial = kwargs.pop('partial', request.method == 'PATCH') serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) return Response(serializer.data)
配置后你可以通过/profile/current/路径发起GET/PUT/PATCH请求,不需要携带任何用户标识。
额外优化点
你已经通过重写get_object直接返回当前登录用户,原来的lookup_field = 'username'配置已经没有作用,可以直接删除。
内容的提问来源于stack exchange,提问作者sadat
相关产品推荐
相关产品推荐

