django-rest-framework实现三种分页

我们通常在使用Django为前端或者用户提供接口的时候,时常会遇到返回大量数据信息的情况,比如:有1000条用户信息,有1000条新闻文章,有1000条商品信息等等。但是我们不可能将所有数据从数据库获取后一股脑的全部返回,这样相当不好,会增大服务器压力,同时也会增加前端渲染压力,也不方便前端或者用户使用。

这种情况下,我们就需要用到分页处理。顾名思义,就是将大量数据进行分页,每页只有少量数据,在用户希望通过接口获取数据时,只需要在url中加入指定的参数,就可以获取指定页的数据,使用相当方便。

在Django中,我们通常使用django-rest-framework这个插件进行分页,它提供了三种分页器PageNumber分页(普通分页)、LimitOffset分页(偏移分页)、Cursor分页(加密分页),我们可以根据实际情况选择合适的分页器,下面来依次介绍这三种分页器。

一、PageNumber分页

class TestApi1(APIView):
    """PageNumber分页"""
    def get(self, request):
        page = PageNumberPagination()  # 创建普通分页器对象
        page.page_size = 3  # 设置每页数据条数
        articles = Articles.get_articles()  # 获取所有文章数据
        ret_page = page.paginate_queryset(articles, request, self)  # 用实例化的分页器对所有数据进行分页,并且返回当前页的数据的列表
        articles_serializer = ArticlesSerializers(ret_page, many=True)  # 将当前页数据序列化
        data = {
            'count': articles.count(),  # 获取数据总数
            'previous': page.get_previous_link(),  # 获取上一页链接,如果没有则是None
            'next': page.get_next_link(),  # 获取下一页链接,如果没有则是None
            'results': articles_serializer.data,  # 当前页的序列化数据
        }
        return Response(data, status=200)

在调用接口时,需要添加page参数,表示获取哪一页,如果没有使用该参数,默认获取第一页,如果传入不存在的页数,则会返回404。

我这里的本地的api是:http://127.0.0.1:8000/api/v1/blog/test1,没有加参数表示获取第一页

观察数据,的确是我想要的格式,这样就可以了。再加入page参数试试:

二、LimitOffset分页

class TestApi2(APIView):
    """LimitOffset分页"""
    def get(self, request):
        page = LimitOffsetPagination()  # 创建偏移分页器对象
        page.page_size = 3  # 设置每页数据默认条数,在api中可以通过limit参数修改
        articles = Articles.get_articles()  # 获取所有文章数据
        ret_page = page.paginate_queryset(articles, request, self)  # 用实例化的分页器对所有数据进行分页,并且返回当前页的数据的列表
        articles_serializer = ArticlesSerializers(ret_page, many=True)  # 将当前页数据序列化
        data = {
            'count': articles.count(),  # 获取数据总数
            'previous': page.get_previous_link(),  # 获取上一页链接,如果没有则是None
            'next': page.get_next_link(),  # 获取下一页链接,如果没有则是None
            'results': articles_serializer.data,  # 当前页的序列化数据
        }
        return Response(data, status=200)

调用接口时,需要传入两个参数:offset、limit,其中,offset表示偏移量,即若offset=0,则从第一条数据算起,若offset=6,则从第七条数据开始算起,limit表示往后偏移多少,如:offset=2&limit=5表示从第3条数据是算起之后的第5条。若不传参数默认获取第一页。

三、Cursor分页

Cursor分页(加密分页)和以上两种分页不太一样,它不能通过自由的传参来获取指定的页面,只能通过返回给你的上一页下一页的url来实现一页一页的跳转。其中还需要注意,Cursor分页默认会用created这个字段来排序,如果你的数据表中没有该字段,则可以使用分页器的ordering属性来自定义排序字段。

class TestApi3(APIView):
    """Cursor分页"""
    def get(self, request):
        page = CursorPagination()  # 创建加密分页器对象
        page.ordering = '-id'  # 设置排序字段,按照id降序排列
        page.page_size = 3  # 设置每页数据条数
        articles = Articles.get_articles()  # 获取所有文章数据
        ret_page = page.paginate_queryset(articles, request, self)  # 用实例化的分页器对所有数据进行分页,并且返回当前页的数据的列表
        articles_serializer = ArticlesSerializers(ret_page, many=True)  # 将当前页数据序列化
        data = {
            'count': articles.count(),  # 获取数据总数
            'previous': page.get_previous_link(),  # 获取上一页链接,如果没有则是None
            'next': page.get_next_link(),  # 获取下一页链接,如果没有则是None
            'results': articles_serializer.data,  # 当前页的序列化数据
        }
        return Response(data, status=200)

第一步只能获取第一页:

这时可以看到我们获取到了加密后的下一页的url,我们可以通过请求这个url来获取下一页的数据。


通过以上描述,我们可以看到,我们每一个视图我们都需要去实例化一个分页器,然后去修改分页器的一些属性值来达到我们希望看到的效果,另外为了让数据清洗明了,我们每一次都还要单独去定义一个data,来声明返回数据的格式,虽然也不是很繁琐,但是如果太多的话也不太好。

在django-rest-framework中,使用通用视图视图集时是能够自动执行分页的。我们需要在配置文件中进行设置。

实现PageNumber分页(以通用视图ListAPIView为例)

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 3,
}
class TestApi4(ListAPIView):
    """PageNumber分页"""
    queryset = Articles.get_articles()
    serializer_class = ArticlesSerializers

看,数据格式已经为我们定义好了,相当方便。

实现LimitOffset分页(以通用视图ListAPIView为例)

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 3,
}
class TestApi5(ListAPIView):
    """LimitOffset分页"""
    queryset = Articles.get_articles()
    serializer_class = ArticlesSerializers

 

实现Cursor分页(以通用视图ListAPIView为例)

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
    'PAGE_SIZE': 3,
}
class TestApi6(ListAPIView):
    """Cursor分页"""
    queryset = Articles.get_articles()
    serializer_class = ArticlesSerializers
    pagination_class = CursorPagination
    pagination_class.ordering = '-id'

以上就是django-rest-framework分页功能的基本实现,一般都是够用的,如果需要有一些个性化的配置等等,可以参考官方文档。

发布了49 篇原创文章 · 获赞 10 · 访问量 9244

猜你喜欢

转载自blog.csdn.net/heibuliuqiu_gk/article/details/103033298