【问题标题】:use GenericAPIView for different seriailizers based on different condition根据不同的条件对不同的序列化程序使用 GenericAPIView
【发布时间】:2017-04-02 04:09:11
【问题描述】:

由于基于特定条件使用不同的序列化程序,我更喜欢使用 APIView 并覆盖 get 函数。我对 APIView 很满意,但现在我需要分页功能,我很难实现它。这就是我想切换到 GenericAPIView 的原因,但由于使用了多个序列化程序,我不知道该怎么做。

class ItemsAPIView(APIView):
    permission_classes = (permissions.IsAuthenticated,)
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

    def get(self, request, format=None):
        """
        Return a list of all devices of this user.
        """
        reply = {}
        try:
            products = BaseItem.objects.owned_items().filter(owner=request.user)
            reply['data'] = OwnedItemSerializer(products, many=True).data

            items = BaseItem.objects.dev_items().filter(owner=request.user)
            reply['data'].extend(ItemSerializer(items, many=True).data)

        except:
            reply['data'] = []
        return Response(reply, status.HTTP_200_OK)

更新

我尝试的另一种方法是

class ItemsAPIView(APIView):
    permission_classes = (permissions.IsAuthenticated,)
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

    def get(self, request, format=None):
        """
        Return a list of all items with product of this user.
        """
        reply = {}
        print ('request', request.META.get('REMOTE_ADDR'))
        try:
            products = BaseItem.objects.owned_items().filter(owner=request.user)
            reply['data'] = OwnedItemSerializer(products, many=True).data

            items = BaseItem.objects.dev_items().filter(owner=request.user)
            page = self.paginate_queryset(items)
            print ('page', page) # i always get None even when pass url as api/items?page=1
            if page is not None:
                reply['data'].extend(ItemSerializer(page, many=True).data)
            reply['data'].extend(ItemSerializer(items, many=True).data)

        except:
            reply['data'] = []
        return Response(reply, status.HTTP_200_OK)

    @property
    def paginator(self):
        """
        The paginator instance associated with the view, or `None`.
        """
        if not hasattr(self, '_paginator'):
            print (hasattr(self, '_paginator'))
            if self.pagination_class is None:
                self._paginator = None
            else:
                self._paginator = self.pagination_class()
        return self._paginator

    def paginate_queryset(self, queryset):
        """
        Return a single page of results, or `None` if pagination is disabled.
        """
        print ('queryset', queryset)
        if self.paginator is None:
            return None
        return self.paginator.paginate_queryset(queryset, self.request, view=self)

    def get_paginated_response(self, data):
        """
        Return a paginated style `Response` object for the given output data.
        """
        assert self.paginator is not None
        return self.paginator.get_paginated_response(data)

没有任何方法有效。我哪里做错了?

【问题讨论】:

  • @hybor 感谢您的回复。就我而言,使用了两个序列化程序,所以我不知道如何处理这个问题。
  • 我试过那个 page = self.paginate_queryset(items) print ('page', page) if page is not None: reply['data'].extend(ItemSerializer(page, many=True) .data) reply['data'].extend(ItemSerializer(items, many=True).data) 但即使将 url 作为 ?page=1

标签: python django django-rest-framework


【解决方案1】:

你真的需要两个序列化器吗?
我认为使用单个序列化程序可能是更好的选择和自定义to_representation:

class ItemSerializer(ModelSerializer):
   # Your fields

   def to_representation(self, instance):
       data = super(ItemSerializer, self).to_representation(instance)
       request = self.context.get('request')
       if request and instance.is_owned_by(request.user):
           return self.owner_to_representation(data, instance) # TO IMPLEMENT
       return data

然后,您可以使用通用视图。您的代码更干净、更简单,而且您不必担心分页:

class ItemList(generics.ListAPIView):
    serializer_class = ItemSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_queryset(self):
        return BaseItem.objects.owned_items()| BaseItem.objects.dev_items()

【讨论】:

    【解决方案2】:

    这就像导入分页器并在 APIView 中手动调用它一样简单。

    class PollView(views.APIView):
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication,)
    paginator = CustomPagination()
    
    def get(self, request):
        queryset = Poll.objects.all()
        context = self.paginator.paginate_queryset(queryset, request)
        serializer = PollSerializer(context, many=True)
        return self.paginator.get_paginated_response(serializer.data)
    

    注意:自定义类不是必需的,您可以简单地从脚本顶部的 rest_framework.pagination 导入。我创建了一个继承自 PageNumberPagination 的 CustomPagination 类,以便我可以根据文档设置 page_size 查询 - http://www.django-rest-framework.org/api-guide/pagination/

    【讨论】:

      猜你喜欢
      • 2016-11-01
      • 2020-05-28
      • 1970-01-01
      • 1970-01-01
      • 2014-11-25
      • 1970-01-01
      • 2020-07-17
      • 2021-10-12
      相关资源
      最近更新 更多