宏观上的分页
基本原理:
场景1:电子商务(不完全显示到页面)【下一页】
场景2:即时通讯(微信)到达底部仍然滑动,【滑动】触发获取下一页的操作
场景3:游戏(loading...)本质上也是分页技术
原因:数据量大
分类:
磁盘上的(每次真的只查询一部分数据)
关系型数据库
【场景】:点击下一页,就要查询一次数据库(访问数据库是需要时间的)
内存中只包含一页(40条)的数据,最节省内存,但是时间成本最高
内存上(一次获取了非常多的数据,但是只展示一部分)
【场景】:点击下一页,只需要在内存中再显示一部分(多一页)数据即可
如果将所有的数据都存储在内存中(内存足够大),时间最快,但是最浪费内存
【**】磁盘和内存相结合的阶段
当执行查询的时候,既不只查询一页的数据,也不查询全部的数据
【场景】:例如 用户在浏览商品的时候,平均只会点击3次【下一页】,
系统在分页的时候可以采取只查询"3页"到内存
如果有的用户,在浏览了3页数据之后,仍然点击【下一页】再查询3页的数据
【效果】:如果用户看了6页的数据,只连接了两次数据库
分页的基本原理
1. django框架提供的分页
paginator库:包含全部与分页有关的功能
pgObj = Paginator() 分页器
(1)object_list = 要分页的数据
(2)per_page = 每页显示的记录数
当前页码对应的数据 = pgObj.get_page(页码)
当前页码对应的数据 等价于 pageData(以下全是pageData)
pageData.number 获取当前是第几页
pageData.next_page_number 获取下一页的页码
pageData.has_next 判定是否有下一页
pageData.previous_page_number 获取上一页的页码
pageData.has_previous 判定是否有上一页
# 从 0 开始计数
pageData.start_index 获取当前页面第1个对象索引
pageData.end_index 获取当前页面最后一个对象索引
object_list:当前页面包含的对象
【插入】:
pageData.number|add:1 加法器
2. 页面可以使用
forloop.counter 默认从1开始
forloop.counter0 对循环计数(索引) 从0开始
from django.shortcuts import render, HttpResponse
import pandas as pd
from myApp01 import models
# pandas、numpy、matplotlib、report 等等
# Create your views here.
def initData(request):
if request.method == "GET":
return render(request, "initData.html")
else:
uploadFile = request.FILES.get("myFile")
# DataFrame 类型
df = pd.read_excel(uploadFile)
for index, row in df.iterrows():
modelObj = models.PopulationModel()
for column, value in row.items():
setattr(modelObj, column, value)
modelObj.save()
return HttpResponse("success")
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from myApp01 import myData
# 在当前类中,能否使用全局的变量
memoryData = None
def turnOverPage(request):
# GET方式用于全表分页
if request.method == "GET":
# 从数据库中查询数据
# allData = models.PopulationModel.objects.all()
# 在这里获取要查询的页码
# request.GET/POST/FILES.get("某个页面空间的name属性", 没有获取到提供一个默认值)
curPage = request.GET.get("curPage", 1)
# 在这里如果从内存中获取数据
global memoryData
# 如果内存中的数据不是 null 的
if memoryData is not None and curPage != 1:
print("----数据来自内存---------------")
allData = memoryData
else :
# 如果内存中没有数据,去数据库中获取
print("-----from database !!!!!!!!!!!!!! ")
allData = models.PopulationModel.objects.all()
# 将 allData 中的数据,装载到分页器中
# 最后一页的数据通常不是满的
# orphans设置为5,表示一页的数据最少要有5条,会被合并到前一页
pgObj = Paginator(object_list=allData, per_page=11, orphans=5)
try:
pageData = pgObj.get_page(curPage)
except PageNotAnInteger:
pageData = pgObj.get_page(1)
except EmptyPage:
# 分页器.num_pages,得到使用当前这个分页器分页后的最大页码(最后一页的页码)
pageData = pgObj.get_page(pgObj.num_pages)
# 每次进入 turnOverPage 这个方法,都会重新创建 MyData 的对象,叫md
# 在调用views中的请求时,对象时重新new的(实例化)
# md = myData.MyData()
# md.setMemory(pgObj)
# reData = md.getMemory()
# print("==============从对象中取出数据============")
# print(reData.object_list)
# python文件函数中使用 global 关键字
# global memoryData
memoryData = allData
# 此处存储 memoryData 数据(内存数据)
# print("-----------------向内存存储数据--------------------")
# print("----------分页器的数据长度------------")
# print(len(pgObj.object_list)) # 分页器中所有需要分页的数据对象
# print("----------当前页面的数据长度-------------")
# print(len(pageData.object_list)) # 当前页面数据对象
# 当前查询到的一页的数据(当前页需要使用的属性)
# 向前端传递了 分页器对象(获取最大页码)
ctx = {"pageData": pageData, "pgObj": pgObj}
return render(request, "show.html", context=ctx)