Django REST Framework-使用@action装饰器定义额外的参数

Fab*_*bio 8 django-rest-framework

我想知道是否有可能使用action装饰器定义额外的参数:

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset that provides the standard actions
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(methods=['post'], detail=True)
    def follow(self, request, pk=None):
        user = self.get_object()
        target_user = ???
        Follow.objects.create(user=user, target=target_user)
        return Response(status=status.HTTP_204_NO_CONTENT)
Run Code Online (Sandbox Code Playgroud)

我要实现的是匹配以下路径: api/users/{id}/follow/{target_id}

follow操作将用于让ID为的用户id跟随另一个ID为的用户target_id

更新

由于似乎无法传递额外的参数,因此现在我将数据作为要遵循的用户ID列表发布:

用于验证数据的串行器:

class FollowSerializer(serializers.ModelSerializer):
    user_ids = serializers.ListField(child=serializers.IntegerField(min_value=1), required=False, help_text='User target IDs')
Run Code Online (Sandbox Code Playgroud)

那个行动:

    @action(detail=True, methods=['post'])
    def follow(self, request, pk=None):
        user = self.get_object()
        serializer = FollowSerializer(data=request.data)
        if serializer.is_valid():
            serializer.data['user_ids']
            for user_id in user_ids:
                target_user = User.objects.get(pk=user_id)
                Follow.objects.create(user=user, target=target_user)
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)

我的解决方案存在的问题是,在自动生成的文档页面上,我看到带有UserSerializer字段的表单。

API文档页面

更新2

以下技巧可让自动生成的文档页面显示正确的表单:

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset that provides the standard actions
    """
    queryset = User.objects.all()

    def get_serializer_class(self):
        if self.action == 'follow':
            return FollowSerializer
        else:
            return UserSerializer

    @action(methods=['post'], detail=True)
    def follow(self, request, pk=None):
        ...
Run Code Online (Sandbox Code Playgroud)

API文档页面-正确的表格

JPG*_*JPG 10

您可以将target_idurl 传递为,api/users/{id}/follow/{target_id}但必须将视图更改为,

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset that provides the standard actions
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(methods=['post'], detail=True)
    def follow(self, request, *args, **kwargs):
        user = self.get_object()
        target_user = int(kwargs['target_id'])
        Follow.objects.create(user=user, target=target_user)
        return Response(status=status.HTTP_204_NO_CONTENT)
Run Code Online (Sandbox Code Playgroud)

在urls.py中定义一个单独的内容path()

urlpatterns = [
                  path('users/<int:pk>/follow/<int:target_id>/', UserViewSet.as_view({"post": "follow"}))

              ]
Run Code Online (Sandbox Code Playgroud)


Ahm*_*hab 10

事实上,您可以接受额外的 kwargs,如下 DRF 3.13.x,无需接触路由器,简洁的 DRF:

@action(detail=True, methods=['delete'], url_name='media-delete',
        url_path='delete_media/(?P<media_pk>[^/.]+)')
def delete_media(self, request, pk=None, media_pk=None):
    # do your logic
    return Response({}, status=status.HTTP_202_ACCEPTED)
Run Code Online (Sandbox Code Playgroud)

这将自动覆盖默认路由器额外路由,以响应带有 ModelViewSet 注册路由的 @action 包装器。


soe*_*ace 5

我的解决方案存在的问题是,在自动生成的文档页面上,我看到带有UserSerializer字段的表单。

文档中

装饰器可以另外接受仅为路由视图设置的额外参数。例如:

这意味着任何可用作类属性的东西都可以用作的参数@action(),包括serializer_class

@action(methods=['post'], detail=True, serializer_class=FollowSerializer)
    def follow(self, request, pk=None):
    # ...
    serializer = self.get_serializer(data=request.data)
    # ...
Run Code Online (Sandbox Code Playgroud)

这将导致正确的形式出现在自动生成的文档中。