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进行一些简单的自然语言处理的教程
Mar 31 Python
21行Python代码实现拼写检查器
Jan 25 Python
python异常和文件处理机制详解
Jul 19 Python
Python字符串格式化的方法(两种)
Sep 19 Python
Python实现带参数的用户验证功能装饰器示例
Dec 14 Python
python3实现点餐系统
Jan 24 Python
Pandas读写CSV文件的方法示例
Mar 27 Python
python批量解压zip文件的方法
Aug 20 Python
详解有关PyCharm安装库失败的问题的解决方法
Feb 02 Python
浅析python 定时拆分备份 nginx 日志的方法
Apr 27 Python
Python PyQt5模块实现窗口GUI界面代码实例
May 12 Python
pycharm sciview的图片另存为操作
Jun 01 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
VOLVO车载收音机
2021/03/02 无线电
php学习之流程控制实现代码
2011/06/09 PHP
PHP四舍五入、取整、round函数使用示例
2015/02/06 PHP
PHP中filter函数校验数据的方法详解
2015/07/31 PHP
Laravel框架创建路由的方法详解
2019/09/04 PHP
php实现将数组或对象写入到文件的方法小结【三种方法】
2020/04/22 PHP
一个用js实现控制台控件的代码
2007/09/04 Javascript
将jQuery应用于login页面的问题及解决
2009/10/17 Javascript
window.location.href = window.location.href 跳转无反应 a超链接onclick事件写法
2013/08/21 Javascript
js 动态修改css文件的方法
2014/08/05 Javascript
jQuery获得指定元素坐标的方法
2015/04/14 Javascript
浅析Node.js中的内存泄漏问题
2015/06/23 Javascript
jquery实现定时自动轮播特效
2015/12/10 Javascript
浅析JS获取url中的参数实例代码
2016/06/14 Javascript
JS简单判断函数是否存在的方法
2017/02/13 Javascript
JS中的Replace()传入函数时的用法详解
2017/09/11 Javascript
vue + element-ui实现简洁的导入导出功能
2017/12/22 Javascript
Angular整合zTree的示例代码
2018/01/24 Javascript
vue.js中实现登录控制的方法示例
2018/04/23 Javascript
jQuery实现checkbox全选功能完整实例
2018/07/12 jQuery
JavaScript格式化json和xml的方法示例
2019/01/22 Javascript
Vue源码探究之虚拟节点的实现
2019/04/17 Javascript
nodejs各种姿势断点调试的方法
2020/06/18 NodeJs
[03:48]大碗DOTA
2019/07/25 DOTA
python人人网登录应用实例
2014/09/26 Python
Python爬取个人微信朋友信息操作示例
2018/08/03 Python
python实现一个简单的udp通信的示例代码
2019/02/01 Python
python匿名函数用法实例分析
2019/08/03 Python
Python3使用tesserocr识别字母数字验证码的实现
2021/01/29 Python
python装饰器代码深入讲解
2021/03/01 Python
HTML5中外部浏览器唤起微信分享功能的代码
2020/09/15 HTML / CSS
销售顾问的岗位职责
2013/11/13 职场文书
群众路线班子对照检查材料
2014/09/25 职场文书
向女朋友道歉的话
2015/01/20 职场文书
2015年酒店服务员工作总结
2015/05/18 职场文书
完美处理python与anaconda环境变量的冲突问题
2021/04/07 Python