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

使用DRF APIView与drf_yasg时出现未定义的额外POST接口

解决Swagger中出现未定义的/users/{id}/POST接口问题

问题根源

  1. 你将带pk的/users/{id}/和不带pk的/users/都映射到同一个UserApiView,drf_yasg会默认把视图中定义的所有HTTP方法(比如你的post方法)关联到所有映射的URL上,导致不该存在的/users/{id}/POST接口被生成。
  2. 视图中定义了两个同名的get方法,Python中后定义的方法会覆盖前一个,这会导致/users/的GET请求也执行带pk的逻辑,属于隐藏bug。

方案1:拆分视图(推荐)

把列表操作和详情操作拆分成两个独立的APIView,让每个视图只处理对应URL的方法,Swagger就能正确生成文档:

URL配置修改

urlpatterns = [
    path('users/', UserListApiView.as_view()),
    path('users/<str:pk>/', UserDetailApiView.as_view()),
]

视图拆分实现

class UserListApiView(APIView):
    @swagger_auto_schema(
        request_body=CreateUserSerializer,
        responses={'200': openapi.Response('response description', DetailUserSerializer)}
    )
    def post(self, request):
        # 修正:原代码缺少data参数,序列化器无法正确处理请求数据
        user_data = CreateUserSerializer(data=request.data)
        user_data.is_valid(raise_exception=True)

        new_user = user_data.save()
        return Response(DetailUserSerializer(new_user).data)

    @swagger_auto_schema(
        responses={'200': openapi.Response('response description', DetailUserSerializer(many=True))}
    )
    def get(self, request):
        queryset = UserRepo().get_all()
        serializer = DetailUserSerializer(queryset, many=True)
        return Response({'data': serializer.data})


class UserDetailApiView(APIView):
    @swagger_auto_schema(
        responses={'200': openapi.Response('response description', DetailUserSerializer)}
    )
    def get(self, request, pk=None):
        queryset = UserRepo().get_all()
        user = get_object_or_404(queryset, pk=pk)

        serializer = DetailUserSerializer(user)
        return Response(serializer.data)

方案2:限制带pk URL的允许方法

如果不想拆分视图,可以在映射带pk的URL时,通过as_view()的methods参数限制仅允许GET方法,同时修正视图中get方法覆盖的问题:

URL配置修改

urlpatterns = [
    path('users/', UserApiView.as_view()),
    # 仅允许GET方法访问带pk的接口
    path('users/<str:pk>/', UserApiView.as_view(methods=['GET'])),
]

视图修正

class UserApiView(APIView):
    @swagger_auto_schema(
        request_body=CreateUserSerializer,
        responses={'200': openapi.Response('response description', DetailUserSerializer)}
    )
    def post(self, request):
        # 修正:原代码缺少data参数
        user_data = CreateUserSerializer(data=request.data)
        user_data.is_valid(raise_exception=True)

        new_user = user_data.save()
        return Response(DetailUserSerializer(new_user).data)

    @swagger_auto_schema(
        responses={
            '200': openapi.Response(
                'response description', 
                DetailUserSerializer(many=True) if not pk else DetailUserSerializer
            )
        }
    )
    def get(self, request, pk=None):
        if pk is None:
            queryset = UserRepo().get_all()
            serializer = DetailUserSerializer(queryset, many=True)
            return Response({'data': serializer.data})
        else:
            queryset = UserRepo().get_all()
            user = get_object_or_404(queryset, pk=pk)
            serializer = DetailUserSerializer(user)
            return Response(serializer.data)

内容的提问来源于stack exchange,提问作者Alexandr Sokolov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:21:21