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中函数默认值使用注意点详解
Jun 01 Python
机器学习python实战之决策树
Nov 01 Python
python实现聚类算法原理
Feb 12 Python
Python格式化日期时间操作示例
Jun 28 Python
python使用rpc框架gRPC的方法
Aug 24 Python
Python实现的爬取百度文库功能示例
Feb 16 Python
Python函数的参数常见分类与用法实例详解
Mar 30 Python
django富文本编辑器的实现示例
Apr 10 Python
使用python实现哈希表、字典、集合操作
Dec 22 Python
详解Python 实现 ZeroMQ 的三种基本工作模式
Mar 24 Python
python3 配置logging日志类的操作
Apr 08 Python
python实现测试工具(一)——命令行发送get请求
Oct 19 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 中文处理技巧
2010/04/25 PHP
PHP中上传多个文件的表单设计例子
2014/11/19 PHP
PHP中imagick函数的中文解释
2015/01/21 PHP
浅谈PHP中JSON数据操作
2015/07/01 PHP
PHP 访问数据库配置通用方法(json)
2018/05/20 PHP
PHP中define() 与 const定义常量的区别详解
2019/06/25 PHP
PHP实现的AES 128位加密算法示例
2019/09/16 PHP
Javascript实现的分页函数
2007/02/07 Javascript
jQuery对象数据缓存Cache原理及jQuery.data方法区别介绍
2013/04/07 Javascript
模拟一个类似百度google的模糊搜索下拉列表
2014/04/15 Javascript
使用js复制链接中的部分文字的方法
2015/07/30 Javascript
4种JavaScript实现简单tab选项卡切换的方法
2016/01/06 Javascript
JS表格组件BootstrapTable行内编辑解决方案x-editable
2016/09/01 Javascript
js实现获取鼠标当前的位置
2016/12/14 Javascript
利用jquery如何从json中读取数据追加到html中
2017/12/01 jQuery
angular实现input输入监听的示例
2018/08/31 Javascript
vue组件中的样式属性scoped实例详解
2018/10/30 Javascript
JavaScript如何实现元素全排列实例代码
2019/05/14 Javascript
[40:57]TI4 循环赛第二日 iG vs EG
2014/07/11 DOTA
python基础教程之实现石头剪刀布游戏示例
2014/02/11 Python
python对数组进行反转的方法
2015/05/20 Python
python中argparse模块用法实例详解
2015/06/03 Python
Python用for循环实现九九乘法表
2018/05/31 Python
pycharm修改文件的默认打开方式的步骤
2019/07/29 Python
Java ExcutorService优雅关闭方式解析
2020/05/30 Python
Django和Ueditor自定义存储上传文件的文件名
2021/02/25 Python
CSS3的resize属性使用初探
2015/09/27 HTML / CSS
基于css3 animate制作绚丽的动画效果
2015/11/24 HTML / CSS
Ajax请求总共有多少种Callback
2016/07/17 面试题
集体婚礼证婚词
2014/01/13 职场文书
在校大学生的职业生涯规划书
2014/03/14 职场文书
奥巴马胜选演讲稿
2014/05/15 职场文书
运动会演讲稿200字
2014/08/25 职场文书
反四风个人对照检查材料
2014/09/26 职场文书
黄石寨导游词
2015/02/05 职场文书
「海贼王」112.9万粉丝纪念图标公布
2022/03/21 日漫