文档章节

Django原生sql也能使用Paginator分页

张豪飞
 张豪飞
发布于 2017/11/14 17:28
字数 689
阅读 117
收藏 5

0x00 Django分页局限

使用Django肯定经常使用Paginator分页,很便捷。但是他可接受的分页对象必须是django orm的查询集或者list、tuple。

当需要使用原生sql查询数据且分页就无法使用Paginator。

0x01 分页原理

其实分页就是传入数据集、每页数量、当前页数,然后计算(查询)数据总数量,根据每页数量计算出总页数,当前页的开始index和结束index,然后根据开始index结束index获取本页数据返回。

请注意上面一句话的黑体字部分,它们就是计算分页的核心,那么Paginator其实只需要实现两个方法count__getslice__就可以自定义一个让Paginator支持的对象,然后就可以使用Paginator分页了,不需要单独对原生sql写分页逻辑

0x02 自定义分页

# coding=utf-8

from django.core.paginator import Paginator


def paginator(data_list, per_page, page_no):
    """封装Django分页"""
    pages = Paginator(data_list, per_page)

    # 防止超出页数
    if not page_no > 0:
        page_no = 1
    if page_no > pages.num_pages:
        page_no = pages.num_pages

    p = pages.page(page_no)  # 获取本页数据

    data = dict()  # 获取分页信息
    data['count'] = pages.count
    data['page_num'] = pages.num_pages
    data['per_page'] = per_page
    data['current'] = page_no
    data['start_index'] = p.start_index() - 1

    return p.object_list, page_no, data


class QueryWrapper(object):
    """查询集包装器。实现django Paginator需要的必要方法,实现和query一样使用Paginator分页"""

    def __init__(self, sql, params=None, db="default"):
        """
        :param sql: sql语句
        :param params: sql语句的params参数
        :param db: 数据库名称(Django配置)
        """
        self.db = db
        self.sql = sql
        self.params = params

    def count(self):
        """计算总页数"""
        sql = """select count(*) from (%s) _count""" % self.sql
        # sql封装方法请参考https://my.oschina.net/watcher/blog/1573503
        return fetchone_sql((sql, self.params), db=self.db, flat=True)  # 返回总页数

    def __getslice__(self, x, y):
        """ self.__getslice(x, y) = self[x:y]"""
        sql = self.sql + ' LIMIT {start}, {num}'.format(start=x, num=y - x)
        # sql封装方法请参考https://my.oschina.net/watcher/blog/1573503
        return fetchall_to_dict((sql, self.params), db=self.db)  # 字典列表形式返回


def demo_orm():
    """使用Django的ORM分页"""
    # 示例:查询status=1的用户分页,每页10条,取第2页数据(假设数据量足够)
    status = 1
    per_page = 10
    page_no = 2

    # 使用Django的ORM
    from django.contrib.auth.models import User

    query = User.objects.filter(status=status).values("id", "username", "first_name")
    one_page_data_list, page_no, page_data = paginator(query, per_page, page_no)
    # one_page_data_list 即为第二页数据,例如:[{"id": 1, "username": "111", "first_name": "aaa"}]
    print one_page_data_list


def demo_raw():
    """使用原生sql实现相同分页"""
    # 示例:查询status=1的用户分页,每页10条,取第2页数据(假设数据量足够)
    status = 1
    per_page = 10
    page_no = 2

    sql = "select id, username, first_name from auth_user where status=%(status)s"
    params = {"status": status}  # 使用params防止sql注入
    query = QueryWrapper(sql, params, "default")
    one_page_data_list, page_no, page_data = paginator(query, per_page, page_no)
    # one_page_data_list 同ORM获取数据一样
    print one_page_data_list


if __name__ == "__main__":
    demo_orm()
    demo_raw()

© 著作权归作者所有

共有 人打赏支持
张豪飞
粉丝 27
博文 36
码字总数 19506
作品 0
郑州
程序员
Django+boostrap分页(1)

源起 我想要优雅地使用+ 来实现分页,忽然发现不知道该如何做起我照葫芦画瓢知道了怎么使用列表组件,也大概知道怎么使用,但是放到一起我就彻底懵逼了。 资料收集 基本分页演示 如果想使用禁...

mhye
2016/10/09
80
0
django paginator基本使用方法

分页是Web应用常用的手法,Django提供了一个分页器类Paginator(django.core.paginator.Paginator),可以很容易的实现分页的功能。该类有两个构造参数,一个是数据的集合,另一个是每页放多少...

jacked
2015/11/13
0
0
Django Paginator属性及方法

Django分页的基本操作在Django文档有简单的例子,基本上看一下就知道。核心代码在django.core.paginator.py中。 分页对象Paginator: 只需提供两个必要的参数,第一个就是用于展示的数据(o...

北方攻城师
2015/06/17
0
0
Django-----分页

一、目的 因为往往数据库中的数据在前端页面展示出来一页肯定是不够的,而一个网页的容量就那么大,所以肯定要分页显示。 二、实施 其实仔细想想,如果数据量小的话,直接在后台的views处理函...

AltBoy
2017/06/26
0
0
如何用Django分页器实现文章分页?

1、概述 Django有自带的分页器,可以将数据分在不同的页面中,并提供一些属性和方法实现对分页数据的操作。分页功能的类位于django/core/paginator.py中。 2、数据准备 在具体实现分类器功能...

mcyJacky的博客
2017/12/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSX | SafariBookmarksSyncAgent意外退出解决方法

1. 启动系统, 按住⌘-R不松手2. 在实用工具(Utilities)下打开终端,输入csrutil disable, 然后回车; 你就看到提示系统完整性保护(SIP: System Integrity Protection)已禁用3. 输入reboot回车...

云迹
今天
4
0
面向对象类之间的关系

面向对象类之间的关系:is-a、has-a、use-a is-a关系也叫继承或泛化,比如大雁和鸟类之间的关系就是继承。 has-a关系称为关联关系,例如企鹅在气候寒冷的地方生活,“企鹅”和“气候”就是关...

gackey
今天
4
0
读书(附电子书)|小狗钱钱之白色的拉布拉多

关注公众号,在公众号中回复“小狗钱钱”可免费获得电子书。 一、背景 之前写了一篇文章 《小狗钱钱》 理财小白应该读的一本书,那时候我才看那本书,现在看了一大半了,发现这本书确实不错,...

tiankonguse
今天
4
0
Permissions 0777 for ‘***’ are too open

异常显示: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ......

李玉长
今天
5
0
区块链10年了,还未落地,它失败了吗?

导读 几乎每个人,甚至是对通证持怀疑态度的人,都对区块链的技术有积极的看法,因为它有可能改变世界。然而,区块链技术问世已经10年了,我们仍然没有真正的用上区块链技术。 几乎每个人,甚...

问题终结者
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部