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使用chardet判断字符编码
May 09 Python
编写Python CGI脚本的教程
Jun 29 Python
Python实现把json格式转换成文本或sql文件
Jul 10 Python
TensorFlow实现MLP多层感知机模型
Mar 09 Python
python如何为创建大量实例节省内存
Mar 20 Python
Python当中的array数组对象实例详解
Jun 12 Python
python求质数列表的例子
Nov 24 Python
python GUI库图形界面开发之PyQt5菜单栏控件QMenuBar的详细使用方法与实例
Feb 28 Python
MxNet预训练模型到Pytorch模型的转换方式
May 25 Python
Django实现后台上传并显示图片功能
May 29 Python
Python文件操作及内置函数flush原理解析
Oct 13 Python
pytorch中F.avg_pool1d()和F.avg_pool2d()的使用操作
May 22 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
匹配csdn用户数据库与官方用户的重合度并将重叠部分的用户筛选出来
2011/12/25 PHP
第二章 PHP入门基础之php代码写法
2011/12/30 PHP
php中使用临时表查询数据的一个例子
2013/02/03 PHP
使用 PHPStorm 开发 Laravel
2015/03/24 PHP
PHP通过curl获取接口URL的数据方法
2018/05/31 PHP
Laravel程序架构设计思路之使用动作类
2018/06/07 PHP
编写跨浏览器的javascript代码必备[js多浏览器兼容写法]
2008/10/29 Javascript
JavaScript 面向对象编程(2) 定义类
2010/05/18 Javascript
js实现翻页后保持checkbox选中状态的实现方法
2012/11/03 Javascript
javascript运算符——逻辑运算符全面解析
2016/06/27 Javascript
jQuery实现选项卡功能(两种方法)
2017/03/08 Javascript
Node.js利用断言模块assert进行单元测试的方法
2017/09/28 Javascript
AngularJS 教程及实例代码
2017/10/23 Javascript
jQuery中each方法的使用详解
2018/03/18 jQuery
Node.js 路由的实现方法
2019/06/05 Javascript
Python脚本实现下载合并SAE日志
2015/02/10 Python
python调用系统ffmpeg实现视频截图、http发送
2018/03/06 Python
Python中偏函数用法示例
2018/06/07 Python
Python画柱状统计图操作示例【基于matplotlib库】
2018/07/04 Python
使用Python编写Prometheus监控的方法
2018/10/15 Python
python3安装speech语音模块的方法
2018/12/24 Python
利用python求积分的实例
2019/07/03 Python
Python简单处理坐标排序问题示例
2019/07/11 Python
理解Django 中Call Stack机制的小Demo
2020/09/01 Python
Python pymysql模块安装并操作过程解析
2020/10/13 Python
适合各种场合的美食礼品:Harry & David
2016/08/03 全球购物
巴西最好的男鞋:Rafarillo
2018/05/25 全球购物
英国著名书店:Foyles
2018/12/01 全球购物
医学专业大学生求职信
2014/07/12 职场文书
教师拔河比赛广播稿
2014/10/14 职场文书
万能检讨书
2015/01/27 职场文书
国情备忘录观后感
2015/06/04 职场文书
小学开学典礼新闻稿
2015/07/17 职场文书
英语教学课后反思
2016/02/15 职场文书
Python进阶学习之带你探寻Python类的鼻祖-元类
2021/05/08 Python
Spring 使用注解开发
2022/05/20 Java/Android