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 相关文章推荐
Windows下为Python安装Matplotlib模块
Nov 06 Python
详解Python进程间通信之命名管道
Aug 28 Python
详谈在flask中使用jsonify和json.dumps的区别
Mar 26 Python
python实现音乐下载器
Apr 15 Python
将TensorFlow的模型网络导出为单个文件的方法
Apr 23 Python
python 3.6.4 安装配置方法图文教程
Sep 18 Python
用python代码将tiff图片存储到jpg的方法
Dec 04 Python
在Pycharm中使用GitHub的方法步骤
Jun 13 Python
关于 Python opencv 使用中的 ValueError: too many values to unpack
Jun 28 Python
Django中文件上传和文件访问微项目的方法
Apr 27 Python
面向新手解析python Beautiful Soup基本用法
Jul 11 Python
基于Python的接口自动化读写excel文件的方法
Jan 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设计模式 State (状态模式)
2011/06/26 PHP
PHP与MYSQL中UTF8 中文排序示例代码
2014/10/23 PHP
PHP实现类似于C语言的文件读取及解析功能
2017/09/01 PHP
新手常遇到的一些jquery问题整理
2010/08/16 Javascript
js通过googleAIP翻译PHP系统的语言配置的实现代码
2011/10/17 Javascript
Javascript 面向对象(一)(共有方法,私有方法,特权方法)
2012/05/23 Javascript
js下拉框二级关联菜单效果代码具体实现
2013/08/03 Javascript
javascript作用域链(Scope Chain)用法实例解析
2015/11/30 Javascript
FullCalendar日历插件应用之数据展现(一)
2015/12/23 Javascript
浅谈JavaScript 数据属性和访问器属性
2016/09/01 Javascript
微信小程序 wxapp视图容器 view详解
2016/10/31 Javascript
最细致的vue.js基础语法 值得收藏!
2016/11/03 Javascript
火狐和ie下获取javascript 获取event的方法(推荐)
2016/11/26 Javascript
webpack 开发和生产并行设置的方法
2018/11/08 Javascript
JavaScript实现轮播图特效
2020/04/10 Javascript
el-form 多层级表单的实现示例
2020/09/10 Javascript
Vue router安装及使用方法解析
2020/12/02 Vue.js
Django分页查询并返回jsons数据(中文乱码解决方法)
2018/08/02 Python
对numpy下的轴交换transpose和swapaxes的示例解读
2019/06/26 Python
对django 模型 unique together的示例讲解
2019/08/06 Python
python3应用windows api对后台程序窗口及桌面截图并保存的方法
2019/08/27 Python
基于Python中的yield表达式介绍
2019/11/19 Python
python实现自动化报表功能(Oracle/plsql/Excel/多线程)
2019/12/02 Python
python @propert装饰器使用方法原理解析
2019/12/25 Python
Python3 shelve对象持久存储原理详解
2020/03/23 Python
python删除指定列或多列单个或多个内容实例
2020/06/28 Python
python更新数据库中某个字段的数据(方法详解)
2020/11/18 Python
俄罗斯便宜的在线服装商店:GroupPrice
2020/04/10 全球购物
班组安全员工作职责
2014/02/01 职场文书
标准版离职证明书
2014/09/12 职场文书
2015年教师新年寄语
2014/12/08 职场文书
社团个人总结范文
2015/03/05 职场文书
土木工程毕业答辩开场白
2015/05/29 职场文书
迎新生晚会主持词
2015/06/30 职场文书
Nginx安装完成没有生成sbin目录的解决方法
2021/03/31 Servers
在JavaScript中如何使用宏详解
2021/05/06 Javascript