一、分页插件Paginator
在做分页时,需要在url后需要拼接参数: ?page=0&size=10
需要导入Paginator 插件类
from django.core.paginator import Paginator
第一步,获取到page和size,注意page需要从1开始,否则会报错,另外可以指定默认的page=1,size=10:
page = request.GET.get('page', '1') # 默认跳转到第一页
size = request.GET.get('size', '10')
第二步,获取到QuerySet结果集:
notes = Note.objects.all().filter(student_id=uid, delete_datetime=None)
第三步,创建Paginator对象,传入结果集和分页的大小:
page_obj = Paginator(notes, size)
第四步,根据页数来获取最终的结果集,可以直接使用object_list来获取到结果:
page_data = page_obj.get_page(page)
res = page_data.object_list
print("res",res)
打印结果:
<TimestampQuerySet [<Note: 第一节课,第一条笔记>, <Note: 第一节课,第二条笔记>, <Note: >, <Note: >, <Note: >, <Note: >, <Note: >, <Note: >]>
二、分页的坑
坑一:
如果分页的页数大于总页数,该分页插件会取到最大的那个页数进行展示!
如下, 查询出的结果中总共有2页,每页5条,我在传分页的时候使用page=3 & size= 5 时,会出现django框架会自动选择第二页的情况!
但是我明明传的page是3 !!!!!
解决方法:
如果传入的page> total_page,那么就返回[] , page 是字符串的话需要先转换为int类型。
page_obj = Paginator(invoice_heads, size)
page_data = page_obj.get_page(page)
total_page = page_obj.num_pages
if page > total_page:
r.data = []
else:
res = page_data.object_list
data = []
for i in res:
d = InvoiceHeadSerializers(i).data
line = InvoiceLine.objects.filter(head=i).values('goods_name').annotate(
max_amount=Max("amount")).first()
if line is not None and "main_goods_name" not in d:
d["main_goods_name"] = line["goods_name"]
else:
d["main_goods_name"] = ""
d["rate_amount"] = i.total_amount - i.amount
data.append(d)
r.data = data
坑二:
如果对查询出来的queryset不排序,使用Paginator做分页时,会出现警告:
UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list
解决方法一,在代码后面拼接.order_by("id")方法
records = VATTaxReportRecords.objects.filter(
~Q(certificate_serial_number=None),
status="S",
resource_uid=resource_uid,
user_id=user_id,
).order_by("id")
方法二,在model里的Meta里添加属性ordering
class Meta:
verbose_name_plural = "报表记录"
verbose_name = "报表记录"
db_table = "tax_report_records"
ordering = [‘id’]