使用自定义post方法和模型覆盖Django REST ViewSet

时间:2015-03-10 07:08:23

标签: python django django-rest-framework

我在Django的REST框架中有一个ModelViewSet,它让我能够通过以下地址进行POST和GET:

api/v1/users

这些用户与评论表具有相反的关系,我希望能够通过URL访问这些评论:

api/v1/users/<username>/comments

我可以通过覆盖@detail_routequeryset设置自定义serializer_class来实现此目的,但它仅适用于GET请求。如果我尝试通过REST Framework的管理部分发布新评论,我会收到一条错误通知,指出“'ListSerializer'对象不可迭代”

这是我的代码:

class UserViewSet(viewsets.ModelViewSet):
    queryset         = User.objects.all()
    serializer_class = UserFlat
    lookup_field     = 'username'


    @detail_route(methods=['post','get'])
    def comment(self, request, **kwargs):

        user = self.get_object()

        self.queryset         = Comment.objects.filter(recipient=user.id)
        self.serializer_class = CommentFlat

        serializer = CommentFlat(instance=self.queryset, many=True)

        return Response(serializer.data)

新评论应采用以下参数:

comment.author,comment.message,comment.recipient

我可以在管理面板中输入所有这些字段,并尝试创建一个帖子请求,但它失败了。理想情况下,我只需填写comment.message和comment.author,而comment.recipient字段应使用user.id自动填充,该地址在网址api/v1/users/<username>/comments

中获取

有谁知道为什么我的帖子请求没有完成以及如何自动填充该字段?

1 个答案:

答案 0 :(得分:14)

我明白了。对于那些寻找答案的人来说,解决方案是明确定义request.method == 'POST'时发生的操作并将对象传递给序列化器。

    @detail_route(methods=['post','get'])
    def comment(self, request, **kwargs):

        user = self.get_object()

        self.queryset = Comment.objects.filter(recipient=user.id)
        self.serializer_class = CommentFlat

        if request.method == 'POST':

            # request.data is from the POST object. We want to take these
            # values and supplement it with the user.id that's defined
            # in our URL parameter
            data = {
                'comment': request.data['comment'],
                'rating': request.data['rating'],
                'author': request.data['author'],
                'recipient': user.id
            }

            serializer = CommentFlat(data=data)

            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        # Return GET by default
        else:

            serializer = CommentFlat(instance=self.queryset, many=True)

            return Response(serializer.data)