【问题标题】:Django Rest Framework: Get singular object using the root APIDjango Rest Framework:使用根 API 获取奇异对象
【发布时间】:2019-09-10 11:13:45
【问题描述】:

我正在尝试设置一个返回单个对象的 API 端点。

现在我有:

class ShoppingCartViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    """
    API endpoint that allows users to be viewed or edited.
    """
    serializer_class = ShoppingCartSerializer
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get_paginated_response(self, data):
        return Response(data)

    def get_queryset(self):
        return ShoppingCart.objects.filter(user=self.request.user)

使用ListModelMixin 和过滤器返回一件商品,因为每个用户都有1 个购物车。

问题是filter 函数返回一个查询集,但我只想要一个项目。

我尝试使用RetrieveModelMixin,但它没有在我想要的端点上运行。检索在.../api/shopping-cart/id 上运行,但我想在.../api/shopping-cart 上检索,因为过滤是通过登录的人完成的。

有什么解决办法吗?

【问题讨论】:

    标签: django django-rest-framework mixins django-rest-viewsets


    【解决方案1】:

    我不确定你是否尝试过,但应该值得(虽然我不确定它是否会起作用)

    def get_queryset(self):
        return ShoppingCart.objects.filter(user=self.request.user)[:1]
    

    【讨论】:

    • 其实我确实试过了。问题是 get_queryset 期望返回一个查询集。
    • 我已经更新了我的答案,虽然这是应该改变的其他东西
    【解决方案2】:

    为什么不使用简单的 api 视图而不是 viewset 类?

    from django.http import Http404
    from rest_framework import status, views
    
    class ShoppingCartAPIView(views.APIView):
        authentication_classes = (TokenAuthentication,)
        permission_classes = (IsAuthenticated,)
    
        def get_object(self):
            # use .get if you are really sure it can only be one shopping cart per user
            try:
                return ShoppingCart.objects.get(user=self.request.user)
            except ShoppingCart.DoesNotExist:
                raise Http404()
    
        def get(self, request):
            obj = self.get_object()        
            data = ShoppingCartSerializer().to_representation(obj)
            return Response(data, status=status.HTTP_200_OK)
    
    

    您甚至可以为其他 http 方法创建逻辑,例如 postdelete

    然后将 url 模式 api/shopping-cart 添加为普通 url(在 urls.py 中),而不是路由器。

    【讨论】:

      【解决方案3】:

      我最终解决它的方式仍然是使用 ListModelMixin,因为我需要从视图集中受益。

      我用以下代码覆盖了list() 方法:

      class ShoppingCartViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
          """
          API endpoint that allows users to be viewed or edited.
          """
          serializer_class = ShoppingCartSerializer
          # authentication_classes = (TokenAuthentication,)
          # permission_classes = (IsAuthenticated,)
      
          def get_paginated_response(self, data):
              return Response(data)
      
          def list(self, request, *args, **kwargs):
              instance = ShoppingCart.objects.get(user=self.request.user)
              serializer = self.get_serializer(instance)
              return Response(serializer.data)
      

      它会在根 url .../api/shopping-cart 上返回一个单数项目,而无需传递参数,因为它基于用户进行过滤。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-23
        • 2015-08-25
        • 2018-02-12
        • 1970-01-01
        • 2014-12-14
        • 1970-01-01
        • 1970-01-01
        • 2019-12-23
        相关资源
        最近更新 更多