Django REST如何使用默认方法避免@action装饰器路由冲突错误?
解决DRF ViewSet中retrieve方法无需PK、从令牌获取用户ID的问题
你遇到的错误是因为DRF的ModelViewSet默认已经为retrieve方法注册了一个带PK参数的路由(detail=True),所以不能直接用@action(detail=False)覆盖这个已有路由。想要用默认的retrieve方法实现需求,可以通过以下两种方式解决:
方法一:手动配置路由+重写get_object
- 重写ViewSet的
get_object方法,直接从当前认证用户获取资料,无需PK参数:
from rest_framework import viewsets from rest_framework.authentication import TokenAuthentication from .models import UserProfile from .serializers import UserProfileSerializer class UserProfileViewSet(viewsets.ModelViewSet): serializer_class = UserProfileSerializer authentication_classes = [TokenAuthentication] # 禁用默认的list、create等不需要的动作(可选,根据需求调整) http_method_names = ['get', 'put', 'patch'] def get_object(self): # 从请求的认证用户中直接获取对应资料 return UserProfile.objects.get(user=self.request.user)
- 在
urls.py中手动配置路由,跳过DRF Router的默认带PK路由,直接映射retrieve到不带PK的路径:
from django.urls import path from .views import UserProfileViewSet urlpatterns = [ # 映射GET请求到retrieve方法,路径不带PK path('profile/', UserProfileViewSet.as_view({'get': 'retrieve'}), name='user-profile'), # 如需支持更新,可继续添加put/patch的映射 path('profile/', UserProfileViewSet.as_view({'put': 'update', 'patch': 'partial_update'}), name='user-profile-update'), ]
方法二:继承GenericViewSet+RetrieveModelMixin
如果不需要ModelViewSet自带的其他动作(比如create、list),可以只继承必要的Mixin,避免生成多余路由:
from rest_framework import viewsets, mixins from rest_framework.authentication import TokenAuthentication from .models import UserProfile from .serializers import UserProfileSerializer class UserProfileViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, # 如需更新可添加 viewsets.GenericViewSet): serializer_class = UserProfileSerializer authentication_classes = [TokenAuthentication] def get_object(self): return UserProfile.objects.get(user=self.request.user)
然后同样在urls.py中手动配置路由:
from django.urls import path from .views import UserProfileViewSet urlpatterns = [ path('profile/', UserProfileViewSet.as_view({'get': 'retrieve', 'put': 'update'}), name='user-profile'), ]
核心逻辑说明
- 重写
get_object是关键:跳过DRF默认通过PK查询对象的逻辑,直接从self.request.user(认证令牌解析出的用户)关联获取资料。 - 手动配置路由:绕开DRF Router自动生成的带PK的
retrieve路由,确保接口路径不带PK参数。
内容的提问来源于stack exchange,提问作者Leyla Karzand
相关产品推荐
相关产品推荐

