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中的引用和拷贝浅析
Nov 22 Python
以Flask为例讲解Python的框架的使用方法
Apr 29 Python
python中pass语句用法实例分析
Apr 30 Python
python实现发送邮件及附件功能
Mar 02 Python
python使用正则表达式的search()函数实现指定位置搜索功能
Nov 10 Python
PyQt5实现无边框窗口的标题拖动和窗口缩放
Apr 19 Python
Python OS模块实例详解
Apr 15 Python
Django框架登录加上验证码校验实现验证功能示例
May 23 Python
Python错误的处理方法
Jun 23 Python
如何解决cmd运行python提示不是内部命令
Jul 01 Python
记一次python 爬虫爬取深圳租房信息的过程及遇到的问题
Nov 24 Python
Python3自带工具2to3.py 转换 Python2.x 代码到Python3的操作
Mar 03 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
关于手调机和数调机的选择
2021/03/02 无线电
PHP的开合式多级菜单程序
2006/10/09 PHP
php实现将数组转换为XML的方法
2015/03/09 PHP
PHP实现链式操作的核心思想
2015/06/23 PHP
PHP 7.0新增加的特性介绍
2017/06/08 PHP
php如何获取Http请求
2020/04/30 PHP
Javascript 中的 && 和 || 使用小结
2010/04/25 Javascript
Javascript 面向对象之重载
2010/05/04 Javascript
JavaScript Title、alt提示(Tips)实现源码解读
2010/12/12 Javascript
Js 时间间隔计算的函数(间隔天数)
2011/11/15 Javascript
nodejs教程 安装express及配置app.js文件的详细步骤
2013/05/11 NodeJs
在JavaScript里嵌入大量字符串常量的实现方法
2013/07/07 Javascript
JavaScript获取图片的原始尺寸以宽度为例
2014/05/04 Javascript
实例讲解JavaScript中instanceof运算符的用法
2016/06/08 Javascript
js获取form表单所有数据的简单方法
2016/08/18 Javascript
浅谈react.js 之 批量添加与删除功能
2017/04/17 Javascript
easyui简介_动力节点Java学院整理
2017/07/14 Javascript
js jquery 获取某一元素到浏览器顶端的距离实现方法
2018/09/05 jQuery
微信小程序实现单选功能
2018/10/30 Javascript
js通过循环多张图片实现动画效果
2019/12/19 Javascript
vue-cli设置css不生效的解决方法
2020/02/07 Javascript
Vue如何跨组件传递Slot的实现
2020/12/14 Vue.js
用实例详解Python中的Django框架中prefetch_related()函数对数据库查询的优化
2015/04/01 Python
python文件处理fileinput使用方法详解
2020/01/02 Python
pygame实现飞机大战
2020/03/11 Python
Python如何利用Har文件进行遍历指定字典替换提交的数据详解
2020/11/05 Python
python中的列表和元组区别分析
2020/12/30 Python
英国性感内衣和睡衣品牌:Bluebella
2018/01/26 全球购物
预订全球最佳旅行体验:Viator
2018/03/30 全球购物
项目管理计划书
2014/01/09 职场文书
自我介绍演讲稿
2014/01/15 职场文书
无私奉献演讲稿
2014/09/04 职场文书
党的群众路线教育实践活动查摆问题及整改措施
2014/10/10 职场文书
罗马假日观后感
2015/06/08 职场文书
Django debug为True时,css加载失败的解决方案
2021/04/24 Python
生命的关键成分来自太空?陨石说是的
2022/04/29 数码科技