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 相关文章推荐
bat和python批量重命名文件的实现代码
May 19 Python
CentOS 6.5下安装Python 3.5.2(与Python2并存)
Jun 05 Python
django 开发忘记密码通过邮箱找回功能示例
Apr 17 Python
对Python定时任务的启动和停止方法详解
Feb 19 Python
Django中的用户身份验证示例详解
Aug 07 Python
python 进程间数据共享multiProcess.Manger实现解析
Sep 23 Python
利用python读取YUV文件 转RGB 8bit/10bit通用
Dec 09 Python
python使用ctypes调用扩展模块的实例方法
Jan 28 Python
python数据分析工具之 matplotlib详解
Apr 09 Python
使用Python-OpenCV消除图像中孤立的小区域操作
Jul 05 Python
一文解决django 2.2与mysql兼容性问题
Jul 15 Python
详解pycharm配置python解释器的问题
Oct 15 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强制下载类型的实现代码
2011/04/21 PHP
PHP版国家代码、缩写查询函数代码
2011/08/14 PHP
php错误、异常处理机制(补充)
2012/05/07 PHP
php htmlspecialchars()与shtmlspecialchars()函数的深入分析
2013/06/05 PHP
php上传图片到指定位置路径保存到数据库的具体实现
2013/12/30 PHP
PHP自动补全表单的两种方法
2017/03/06 PHP
PHP+Ajax简单get验证操作示例
2019/03/02 PHP
JavaScript的类型转换(字符转数字 数字转字符)
2010/08/30 Javascript
jQuery EasyUI API 中文文档 - Spinner微调器使用
2011/10/21 Javascript
巧用replace将文字表情替换为图片
2014/04/17 Javascript
javascript实现跨域的方法汇总
2015/06/25 Javascript
Js遍历键值对形式对象或Map形式的方法
2016/08/08 Javascript
关于Vue项目跨平台运行问题的解决方法
2018/09/18 Javascript
Node.js API详解之 zlib模块用法分析
2020/05/19 Javascript
Python学习笔记之os模块使用总结
2014/11/03 Python
理解Python中的With语句
2016/03/18 Python
在pandas多重索引multiIndex中选定指定索引的行方法
2018/11/16 Python
浅谈python编译pyc工程--导包问题解决
2019/03/20 Python
python并发编程多进程之守护进程原理解析
2019/08/20 Python
django inspectdb 操作已有数据库数据的使用步骤
2021/02/07 Python
HTML最新标准HTML5总结(必看)
2016/06/13 HTML / CSS
Osklen官方在线商店:巴西服装品牌
2019/04/25 全球购物
Chinti & Parker官网:奢华羊绒女装和创新针织设计
2021/01/01 全球购物
英国奢侈品在线精品店:Hervia
2020/09/03 全球购物
C#中有没有静态构造函数,如果有是做什么用的?
2016/06/04 面试题
关键字throw与throws的用法差异
2016/11/22 面试题
巧克力蛋糕店创业计划书
2014/01/14 职场文书
土木建筑学生自我评价
2014/01/14 职场文书
学校评语大全
2014/05/06 职场文书
二年级班级文化建设方案
2014/05/10 职场文书
个人遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
学校证明范文
2015/06/24 职场文书
《最后一头战象》教学反思
2016/02/16 职场文书
python爬虫selenium模块详解
2021/03/30 Python
Python实战之实现康威生命游戏
2021/04/26 Python
MySQL系列之十五 MySQL常用配置和性能压力测试
2021/07/02 MySQL