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

时间:2018-08-13 13:18:48

标签: 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)

我要实现的是匹配以下路径: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')

动作:

    @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)

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

API Doc Page

更新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):
        ...

API Doc Page - Correct Form

3 个答案:

答案 0 :(得分:3)

您可以将wp_pagenavi()作为url传递给target_id,但必须将视图更改为,

api/users/{id}/follow/{target_id}

并在urls.py 中将 单独的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)定义为

path()

答案 1 :(得分:3)

  

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

来自the documentation

  

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

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

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

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

答案 2 :(得分:0)

我不确定。查看文档,似乎@action()只会接受.get_extra_actions()获得的特定动作列表

您能否仅将目标的电子邮件地址/帐户名/帐户ID用作后续目标,然后发布该数据?无论如何,似乎这样做会更容易。