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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:05:17