如何让DRF将视图集动作的URL路径设为空并使用基础路径?
如何让DRF将视图集动作的URL路径设为空并使用基础路径?
嘿,我之前也踩过这个坑!DRF的@action装饰器在你传空字符串给url_path时,确实会默认把函数名当作路径后缀,完全不是我们想要的效果。不过有两个靠谱的办法能解决你的需求:
方法一:直接在路由中手动映射(最直接)
如果你不需要依赖router自动生成路由,可以直接在urls.py里手动把patch请求映射到你的视图集方法,这样就能直接用基础路径:
# urls.py from django.urls import path from .views import CurrentUserViewSet urlpatterns = [ path('api/current-user/', CurrentUserViewSet.as_view({'patch': 'update_current_user'}), name='current-user-patch'), ]
然后你的视图集里就不需要加@action装饰器了,直接定义方法就行:
# views.py from rest_framework import viewsets from rest_framework.response import Response class CurrentUserViewSet(viewsets.ViewSet): def update_current_user(self, request): # 这里写你的业务逻辑,比如获取当前用户并更新信息 user = request.user # 示例更新逻辑 user.username = request.data.get('username', user.username) user.save() return Response({"status": "success", "user": {"username": user.username}})
方法二:用@action配合路由配置(适合依赖router的场景)
如果你还是想使用DRF的router来管理路由,可以在@action里把url_path设为'',同时确保视图集是detail=False的配置,另外可以指定url_name来避免路由名称冲突:
# views.py from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.response import Response class CurrentUserViewSet(viewsets.GenericViewSet): @action(detail=False, methods=['patch'], url_path='', url_name='current-user-update') def update_current_user(self, request): # 你的业务逻辑代码 user = request.user user.email = request.data.get('email', user.email) user.save() return Response({"status": "success", "user": {"email": user.email}})
然后在路由注册时,用router正常注册这个视图集:
# urls.py from django.urls import path, include from rest_framework.routers import SimpleRouter from .views import CurrentUserViewSet router = SimpleRouter() router.register(r'api/current-user', CurrentUserViewSet, basename='current-user') urlpatterns = [ path('', include(router.urls)), ]
这样router就会把这个patch动作直接映射到/api/current-user/路径,不会自动添加函数名后缀。
额外小技巧:改用APIView简化逻辑
如果你的视图只需要处理当前用户的patch请求,其实可以直接用DRF的APIView,完全避开ViewSet的路由规则,逻辑更清晰:
# views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated class CurrentUserUpdateView(APIView): permission_classes = [IsAuthenticated] def patch(self, request): user = request.user # 业务逻辑 user.first_name = request.data.get('first_name', user.first_name) user.save() return Response({"status": "success", "user": {"first_name": user.first_name}}) # urls.py from django.urls import path from .views import CurrentUserUpdateView urlpatterns = [ path('api/current-user/', CurrentUserUpdateView.as_view(), name='current-user-patch'), ]
以上几种方法都能实现你想要的效果,根据自己的项目路由习惯选就行~
内容来源于stack exchange
相关产品推荐
相关产品推荐

