我想在我的API中显示分页功能,我正在使用APIView
多个序列化程序。
我知道用ListView
显示分页很容易
我已经看到将ListModelMixin
和APIView
结合起来的地方,但如果我的代码如下:
class ListModelMixin(object):
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serilaizer.data)
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)
如何将它们组合起来以便获得分页结果?
提前谢谢!
答案 0 :(得分:1)
首先,你目前正在做的事情太复杂而没有理由。
为了实现“可分页”查询集,最好在简单的过滤器组合中更改owned_items()
和dev_items()
,而不是模型方法。通过例子澄清:
products = BaseItem.objects.filter(owner=request.user, owned=True)
而不是
products = BaseItem.objects.owned_items().filter(owner=request.user)
这样,您可以生成一个更易于分页的查询集:
user_items = BaseItem.objects.filter(
Q(owner=request.user, owned=True) |
Q(owner=request.user, dev=True)
)
注1:如果您愿意,可以进一步简化,但这超出了您的问题范围。作为思考的食物,请查看:
user_items = BaseItem.objects.filter(owner=request.user).distinct()
注2:您应该为单个模型使用单个序列化程序,因为您正在做的事情会增加复杂性而没有任何好处(高风险 - 低奖励情况)
通过上述提及并假定:
有一些方法可以实现您想要的目标:
利用GeneriAPIView和ListModelMixin,您可以通过自动分页.list()
方法重构您的课程:
from rest_framework import mixins, generics
class ItemsAPIView(mixins.ListModelMixin, generics.GenericAPIView,):
permission_classes = (permissions.IsAuthenticated,)
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
serializer_class = OwnedItemSerializer
# You can define .get in here if you really need it.
# You can also override .list to add specific functionality
如果您不想使用上述内容,并希望保留APIView
,那么您可以保留get
方法并为其提供分页,如此处所述{ {3}}:
class ItemsAPIView(APIView):
permission_classes = (permissions.IsAuthenticated,)
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
serializer_class = MyNewUnifiedSerializerClass
def get(self, request):
user_items = BaseItem.objects.filter(
owner=request.user
).distinct()
page = self.paginate_queryset(user_items)
if page is not None:
serializer = self.serializer_class(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(user_items, many=True)
return Response(serializer.data)
# Now add the pagination handlers taken from
# django-rest-framework/rest_framework/generics.py
@property
def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not 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.
"""
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)