DRF中如何在urls.py调用APIView子类带@action装饰器的方法?
问题分析与解决方案
你的核心问题在于对DRF的装饰器和视图类的匹配使用有误:@action装饰器是ViewSet类的专属特性,APIView并不支持这个装饰器,同时APIView的as_view()方法确实不接受参数字典(这个用法属于ViewSet),所以才会触发TypeError。
下面提供两种可行的解决思路:
方案一:改用ViewSet类适配@action装饰器
如果你想保留@action的用法,需要将APIView替换为ViewSet系列类(比如GenericViewSet),再通过路由注册来映射路径:
修改views.py
from rest_framework.viewsets import GenericViewSet from rest_framework.decorators import action from rest_framework.permissions import AllowAny class UserView(GenericViewSet): @action(methods=['post'], detail=False, permission_classes=[AllowAny], url_path='') def create(self, request): serializer = UserRegSerializer(data=request.data) user_service = UserService() try: serializer.is_valid(raise_exception=True) serialized_data = serializer.validated_data registered_user = user_service.create_user(serialized_data) payload = registered_user.__dict__ response = ResponseGenerator(payload, constants.SUCCESS_KEY) except Exception as e: response = ResponseGenerator(e) return Response(data={"Response": response.get_custom_response()})
url_path=''用来指定该action直接映射到/user路径,而非默认的/user/create/detail=False表示这是一个针对集合的操作,而非单个实例
修改urls.py
使用DRF的路由注册器来绑定视图:
from rest_framework.routers import DefaultRouter from .views import UserView router = DefaultRouter() router.register(r'user', UserView, basename='user') urlpatterns = router.urls
方案二:保留APIView,通过重写权限方法实现不同权限控制
如果不想切换到ViewSet,可以直接在APIView中重写get_permissions方法,根据请求方法返回对应的权限类:
修改views.py
from rest_framework.views import APIView from rest_framework.permissions import AllowAny, IsAuthenticated class UserView(APIView): def get_permissions(self): # 针对POST请求设置AllowAny权限 if self.request.method == 'POST': return [AllowAny()] # 其他请求方法设置默认权限(可根据需求调整) return [IsAuthenticated()] def post(self, request): # 将原create方法的代码移到post方法中 serializer = UserRegSerializer(data=request.data) user_service = UserService() try: serializer.is_valid(raise_exception=True) serialized_data = serializer.validated_data registered_user = user_service.create_user(serialized_data) payload = registered_user.__dict__ response = ResponseGenerator(payload, constants.SUCCESS_KEY) except Exception as e: response = ResponseGenerator(e) return Response(data={"Response": response.get_custom_response()})
修改urls.py
直接使用原有配置即可:
urlpatterns = [ path('user', UserView.as_view()), ]
内容的提问来源于stack exchange,提问作者RIO
相关产品推荐
相关产品推荐

