一、Pagination 分页器编程步骤
-
View, 导入
django.core.paginator.Paginator
类,创建Paginator 对象时,输入qs对象,以及每页显示条数。 -
接收 URL, 从请求参数中读取page数值 ,通过 paginator.page(page_num) 返回请求页的page_obj.
-
模板中,用page_obj的属性来编写分页器HTML代码
分页器功能的两个主要数据结构: Paginator 对象, Page对象。
参考实例: https://simpleisbetterthancomplex.com/tutorial/2016/08/03/how-to-paginate-with-django.htmlexample
from django.core.paginator import Paginator #import Paginator
def movies(request):
movies = Movie.objects.all() #queryset containing all movies we just created
paginator = Paginator(movies, 3) # 每页3行记录
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request=request, template_name="main/movies.html", context={'movies':page_obj})
二、Paginator 对象
paginator 类对象的属性
per_page 每页显示条数。
count, num_pages
page_range, 页面的迭代器
Paginator 对象的方法
Paginator.get_page(number) 返回 page_obj , 页号从1开始
Paginator.page(number) 同上。
三、 Page对象
主要属性
object_list , 即queryset 数据
number, 当前页号
previous_page_number, next_page_number
主要方法
has_next(), has_previous(), next_page_number(), 等, page2.previous_page_number()
>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page2 = p.get_page(2)
>>> page2.has_next()
False
>>> page2.has_previous()
True
>>> page2.has_other_pages()
True
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()
>>> page2.start_index() # The 1-based index of the first item on this page
3
>>> page2.end_index() # The 1-based index of the last item on this page
4
三、分页功能实现
1、URL请求参数携带 page 参数
如:
http://127.0.0.1:8000/books/borrow/?page=1
2、视图中实现分页器,返回页面对象
from django.core.paginator import Paginator #import Paginator
def movies(request):
movies = Movie.objects.all() #queryset containing all movies we just created
paginator = Paginator(movies, 10) # 每页10行记录
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request=request, template_name="main/movies.html", context={'movies':page_obj})
说明:
paginator = Paginator(movies, 10) # 每页10行记录
表示创建分页器对象,构造器传入查询结果,以及每页显示行数。
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
请求参数page表示请求的页号,获取该页的页面对象page_obj
return render(request=request, template_name="main/movies.html", context={'movies':page_obj})
将page_obj 页面对象做为context上下文传给模板渲染。
3、模板中实现分页器渲染
数据列表显示部分
page_obj 页面对象中包含了当前页的object对象列表,用 for …in… 遍历。
{% for obj in page_obj %}
{{ obj.name }}
{% endfor %}`
分页器栏用用a标签实现分页器跳转
Page对象传入模板后,需要编写html分页器代码,判断是否有上下页, 并传回下次请求的页号
<div class='pagination'>
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« 首页</a>
<a href="?page={{ page_obj.previous_page_number }}">上页</a>
{% endif %}
<span class="current">
当前页 {{ page_obj.number }} / {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">下页</a>
<a href="?page={{ page_obj.paginator.num_pages }}">末页 »</a>
{% endif %}
</div>
4、支持用户自定义每页显示行数
有时,用户希望自己控制每页显示行数,可以在GET请求参数中,携带 page_size=xxx, 如
http://127.0.0.1:8000/books/borrow/?page=1&page_size=20
视图函数中,令 paginator.per_page = request.GET[‘page_size’], 即可支持前端修改每页显示条数。
模板中添加1个input标签,监听到 change 事件后,将page_size拼接在地址后面,发送请求到服务器。
<script>
var input = document.getElementById("pagesize");
function handleChange(e){
window.location.href="http://127.0.0.1:8000/books/borrow/?page=1&page_size="+input.value
}
</script>
完整示例代码
views.py
from django.core.paginator import Paginator
from django.shortcuts import render
from myapp.models import *
def listing(request):
qs = Borrow.objects.all()
paginator = Paginator(qs, 25) # Show 25 contacts per page.
if 'page_size' in request.GET.keys():
paginator.per_page = request.GET['page_size'],
page_number = request.GET.get("page")
page_obj = paginator.get_page(page_number)
return render(request, "list.html", {"page_obj": page_obj})
对于通用视图, 重载get()方法
class BorrowListView(ListView):
model = Borrow
template_name = "books/borrow_list.html"
paginate_by = 10 # 默认传至template的context名称为page_obj
def get(self, request, *args, **kwargs):
if 'page_size' in request.GET.keys():
self.paginate_by = request.GET['page_size']
return super().get(request, *args, **kwargs)
list_contact.html
{% extends "myapp/base.html" %}
{% block content %}
{% for obj in page_obj %}
{{ obj.name }}<br>
...
{% endfor %}
<div class='pagination'>
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« 首页</a>
<a href="?page={{ page_obj.previous_page_number }}">上页</a>
{% endif %}
<span class="current">
当前页 {{ page_obj.number }} / {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">下页</a>
<a href="?page={{ page_obj.paginator.num_pages }}">末页 »</a>
{% endif %}
<span style='margin-left: 20px;'>每页显示<span>
<input type='number' min=10 max=100 id="pagesize" style="width: 40px;" onchange='handleChange()' /><span>条记录</span>
</div>
<script>
var input = document.getElementById("pagesize");
function handleChange(e){
window.location.href="http://127.0.0.1:8000/books/borrow/?page=1&page_size="+input.value
}
</script>
{% endblock content %}
最终显示如下
实际应用时,可用 bootsrap pagination类渲染