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使用装饰器和线程限制函数执行时间的方法
Apr 18 Python
python生成excel的实例代码
Nov 08 Python
numpy自动生成数组详解
Dec 15 Python
点球小游戏python脚本
May 22 Python
如何使用python把ppt转换成pdf
Jun 29 Python
python下PyGame的下载与安装过程及遇到问题
Aug 04 Python
Python 在OpenCV里实现仿射变换—坐标变换效果
Aug 30 Python
python子线程退出及线程退出控制的代码
Oct 16 Python
Python基于pyecharts实现关联图绘制
Mar 27 Python
python打开文件的方式有哪些
Jun 29 Python
python将数据插入数据库的代码分享
Aug 16 Python
教你怎么用Python实现GIF动图的提取及合成
Jun 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
ThinkPHP的模版中调用session数据的方法
2014/07/01 PHP
PHP封装的验证码工具类定义与用法示例
2018/08/22 PHP
PHP中PCRE正则解析代码详解
2019/04/26 PHP
jquery实现漂浮在网页右侧的qq在线客服插件示例
2013/05/13 Javascript
JavaScript分析、压缩工具JavaScript Analyser
2014/12/31 Javascript
利用原生js和jQuery实现单选框的勾选和取消操作的方法
2016/09/04 Javascript
详解webpack分包及异步加载套路
2017/06/29 Javascript
vue中element组件样式修改无效的解决方法
2018/02/03 Javascript
vue-cli webpack2项目打包优化分享
2018/02/07 Javascript
jQuery替换节点元素的操作方法
2018/03/18 jQuery
OpenLayers3加载常用控件使用方法详解
2020/09/25 Javascript
Python模块搜索概念介绍及模块安装方法介绍
2015/06/03 Python
Python Sql数据库增删改查操作简单封装
2016/04/18 Python
分享Pycharm中一些不为人知的技巧
2018/04/03 Python
Python实现接受任意个数参数的函数方法
2018/04/21 Python
Python 进程之间共享数据(全局变量)的方法
2019/07/16 Python
浅谈python图片处理Image和skimage的区别
2019/08/04 Python
python 函数嵌套及多函数共同运行知识点讲解
2020/03/03 Python
Django Admin后台添加数据库视图过程解析
2020/04/01 Python
Pycharm-community-2020.2.3 社区版安装教程图文详解
2020/12/08 Python
css3过渡_动力节点Java学院整理
2017/07/11 HTML / CSS
德国传统玻璃制造商:Cristalica
2018/04/23 全球购物
lululemon美国官网:瑜伽服+跑步装备
2018/11/16 全球购物
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?用contains来区分是否有重复的对象。还是都不用
2013/07/30 面试题
中专生学习生活的自我评价分享
2013/10/27 职场文书
幼儿园教师教学反思
2014/02/06 职场文书
小学生开学第一课活动方案
2014/03/27 职场文书
卖车协议书
2014/04/21 职场文书
工作试用期自我评价
2015/03/10 职场文书
2015年教师个人业务工作总结
2015/10/23 职场文书
2016年教师节感言
2015/12/09 职场文书
《山中访友》教学反思
2016/02/24 职场文书
七年级作文之环保作文
2019/10/17 职场文书
Java 通过手写分布式雪花SnowFlake生成ID方法详解
2022/04/07 Java/Android
Apache Hudi 加速传统的批处理模式
2022/04/24 Servers
element tree树形组件回显数据问题解决
2022/08/14 Javascript