Django Rest 框架 - APIView 分页
Posted
技术标签:
【中文标题】Django Rest 框架 - APIView 分页【英文标题】:Django Rest Framework - APIView Pagination 【发布时间】:2016-06-20 05:43:01 【问题描述】:我有一个非常简单的APIView
,但我不知道如何在这里设置分页。
在这种情况下,我选择一个带有给定pk
的Event
,然后我将所有NewsItems
分配给这个Event
。
pagination_class = LimitOffsetPagination
在ListCreateAPIView
开头定义查询集时工作正常,例如。 queryset = Event.objects.all()
但不是自定义get
:
class EventNewsItems(APIView):
pagination_class = LimitOffsetPagination
def get(self, request, pk, format=None):
#user = request.user
event = Event.objects.get(pk=pk)
news = event.get_news_items().all()
serializer = NewsItemSerializer(news, many=True, context='request':request)
response = Response(serializer.data, status=status.HTTP_200_OK)
return response
已解决:
def get(self, request, pk, format=None):
#user = request.user
event = Event.objects.get(pk=pk)
news = event.get_news_items().all()
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(news, request)
serializer = NewsItemSerializer(result_page, many=True, context='request':request)
response = Response(serializer.data, status=status.HTTP_200_OK)
return response
【问题讨论】:
查看这个讨论,看起来这家伙解决了你的问题github.com/tomchristie/django-rest-framework/issues/3030 嘿,@user3128673 我想知道我的回答是否有帮助。 【参考方案1】:另一个选项是从分页类继承,对视图类的更改更少:
from rest_framework.pagination import LimitOffsetPagination
class EventNewsItems(APIView, LimitOffsetPagination):
def get(self, request, pk, format=None):
event = Event.objects.get(pk=pk)
news = event.get_news_items().all()
results = self.paginate_queryset(news, request, view=self)
serializer = NewsItemSerializer(results, many=True)
return self.get_paginated_response(serializer.data)
【讨论】:
谢谢你!有没有办法在每个视图的基础上设置默认限制和偏移量? 彼得保罗的回答让我的评论过时了 最佳解决方案! @FelixPK 您可以在 settings.py 中设置默认的PAGE_SIZE
并使用 limit
和 offset
查询参数。【参考方案2】:
我已经为此主题创建了Q&A style example。 作为排序摘要:
通过利用 Django Rest Frameworks 源代码以及它们如何处理分页,我们在视图类中创建相同的方法并使用它们,就像您的解决方案使用默认方法一样:
取自上述文档:
from rest_framework.settings import api_settings from rest_framework.views import APIView class MyView(APIView): queryset = OurModel.objects.all() serializer_class = OurModelSerializer pagination_class = api_settings.DEFAULT_PAGINATION_CLASS # cool trick right? :) # We need to override get method to achieve pagination def get(self, request): ... page = self.paginate_queryset(self.queryset) if page is not None: serializer = self.serializer_class(page, many=True) return self.get_paginated_response(serializer.data) ... Do other stuff needed (out of scope of pagination) # 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)
【讨论】:
self._paginator = self.pagination_class(). TypeError: 'list' object is not callable
- 我收到此错误。
缩进有点偏离
@GiannisKatsini 确实(我想我已经修复了所有问题)您可以随意编辑您看到的任何内容。【参考方案3】:
另一种分页方法是使用 Paginator 类。
除了答案查询,还必须设置要显示的页数和页面将包含的元素范围。
页码和项目范围可以作为请求参数的一部分提供,也可以通过您选择的方式提供。
以问题的情况为例:
from django.core.paginator import Paginator
class EventNewsItems(APIView):
def get(self, request, pk, format=None):
#user = request.user
event = Event.objects.get(pk=pk)
news = event.get_news_items().all()
# -----------------------------------------------------------
page_number = self.request.query_params.get('page_number ', 1)
page_size = self.request.query_params.get('page_size ', 10)
paginator = Paginator(news , page_size)
serializer = NewsItemSerializer(paginator.page(page_number) , many=True, context='request':request)
# -----------------------------------------------------------
response = Response(serializer.data, status=status.HTTP_200_OK)
return response
【讨论】:
如果您想在每次观看的基础上处理限制和偏移,那就太好了! 如果您请求的页面为空,您将收到异常。您将需要处理django.core.paginator.EmptyPage
异常以上是关于Django Rest 框架 - APIView 分页的主要内容,如果未能解决你的问题,请参考以下文章
python Django Rest_Framework框架 APIView介绍与序列化器详解(图文并茂版)
python Django Rest_Framework框架 APIView介绍与序列化器详解(图文并茂版)
将 APIView 添加到 Django REST Framework 可浏览 API [重复]
即使我使用了 ScrapyItem.objects.all(),我在 django rest 框架的 APIView 内的 post 方法中也只得到一个对象。任何人都知道为啥