Django原生sql也能使用Paginator分页的示例代码


Posted in Python onNovember 15, 2017

django-pagination这是一个python包,来自github上的一个项目,很容易用。

不过这是一个懒人工具,好吧(工具理性)。不过当一个页面有多处需要采用分页的话,就行不通了,要么修改django-pagination的源码,改变它的url指向,不过我没研究,当工程涉及到迁移时,要知道要安装各种东西本来就是个缺点,还要再修改源码,那就得不偿失。因而转战django自带的分页插件——Paginator。

Paginator其实只需要实现两个方法`count`和`__getslice__`就可以自定义一个让Paginator支持的对象

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()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用beautifulsoup从爱奇艺网抓取视频播放
Jan 23 Python
深入理解Python3 内置函数大全
Nov 23 Python
python基于twisted框架编写简单聊天室
Jan 02 Python
python读取文本中数据并转化为DataFrame的实例
Apr 10 Python
详解Python_shutil模块
Mar 15 Python
python设置随机种子实例讲解
Sep 12 Python
django2.2安装错误最全的解决方案(小结)
Sep 24 Python
Python集成开发工具Pycharm的安装和使用详解
Mar 18 Python
Python使用正则表达式实现爬虫数据抽取
Aug 17 Python
Python脚本实现Zabbix多行日志监控过程解析
Aug 26 Python
pycharm 多行批量缩进和反向缩进快捷键介绍
Jan 15 Python
python开发的自动化运维工具ansible详解
Aug 07 Python
使用Python的turtle模块画图的方法
Nov 15 #Python
python绘制铅球的运行轨迹代码分享
Nov 14 #Python
Python实现句子翻译功能
Nov 14 #Python
简述:我为什么选择Python而不是Matlab和R语言
Nov 14 #Python
Python与R语言的简要对比
Nov 14 #Python
Python基础语言学习笔记总结(精华)
Nov 14 #Python
Python利用multiprocessing实现最简单的分布式作业调度系统实例
Nov 14 #Python
You might like
php中用date函数获取当前时间有误的解决办法
2013/08/02 PHP
PHP中isset()和unset()函数的用法小结
2014/03/11 PHP
php简单防盗链实现方法
2015/07/29 PHP
PHP如何将XML转成数组
2016/04/04 PHP
解决jquery1.9不支持browser对象的问题
2013/11/13 Javascript
回车直接实现点击某按钮的效果即触发单击事件
2014/02/27 Javascript
JavaScript AJAX之惰性载入函数
2014/08/27 Javascript
js原型链与继承解析(初体验)
2016/05/09 Javascript
JavaScript实现刷新不重记的倒计时
2016/08/10 Javascript
js 获取本地文件及目录的方法(推荐)
2016/11/10 Javascript
bootstrap table服务端实现分页效果
2017/08/10 Javascript
了解javascript中的Dom操作
2019/05/27 Javascript
简单了解TypeScript中如何继承 Error 类
2019/06/21 Javascript
Vue Element UI + OSS实现上传文件功能
2019/07/31 Javascript
layer实现弹出层自动调节位置
2019/09/05 Javascript
原生js实现无缝轮播图
2020/01/11 Javascript
九步学会Python装饰器
2015/05/09 Python
Python映射拆分操作符用法实例
2015/05/19 Python
Python中字符串对齐方法介绍
2015/05/21 Python
Python中的集合类型知识讲解
2015/08/19 Python
pygame游戏之旅 添加碰撞效果的方法
2018/11/20 Python
Python3.5装饰器典型案例分析
2019/04/30 Python
Python vtk读取并显示dicom文件示例
2020/01/13 Python
python代码如何实现余弦相似性计算
2020/02/09 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
Pretty Little Thing爱尔兰:时尚女性服饰
2017/03/27 全球购物
统计员岗位职责
2013/11/14 职场文书
读书心得体会
2013/12/28 职场文书
结婚邀请函范文
2014/01/14 职场文书
档案室主任岗位职责
2014/02/12 职场文书
中学生逃课检讨书
2015/02/17 职场文书
东京审判观后感
2015/06/01 职场文书
用人单位的规章制度,怎样制定才是有效的?
2019/07/09 职场文书
Python 数据结构之十大经典排序算法一文通关
2021/10/16 Python
把77A收信机改造成收音机
2022/04/05 无线电
服务器nginx权限被拒绝解决案例
2022/09/23 Servers