如何在Django项目中添加分页
分页系统是博客、搜索引擎、结果列表等中最常见的功能之一。看到分页系统的流行,django开发者建立了一个分页器类,这样web开发者就不必考虑制作分页器的逻辑了。
分页器类存在于django/core/paginator.py。所以要使用Paginator类,我们首先需要从django.core.paginator中导入它。
from django.core.paginator import Paginator
语法 :
p = Paginator(list_of_objects, no_of_objects_per_page)
第一个参数是对象的列表,这些对象将分布在各个页面。第二个参数表示将在每个页面上显示的对象的数量。这两个参数是必须的。
然而,分页器类还需要两个可选的参数,如下所示。
- orphans – 它的值必须是一个小于no_of_objects_per_page的整数。它告诉我们最后一页是否有最小数量的对象。如果最后一页的剩余对象的数量小于或等于这个参数的值,那么这些对象将被添加到前一页。默认值是0。
- allow_empty_first_page – 它采用布尔值。是否允许第一页为空。
注意:第一个参数不需要是一个列表。相反,它可以是一个元组,queryset或其他具有count()或__len__()方法的可切分对象。
如何使用分页器类?
假设我们正在开发一个博客网站。我们在models.py中定义了Post模型,并且我们创建了8个这样的帖子。现在在views.py中,我们写了以下代码
from django.shortcuts import render
from .models import Post
from django.core.paginator import Paginator
# Create your views here.
def index(request):
posts = Post.objects.all() # fetching all post objects from database
p = Paginator(posts, 5) # creating a paginator object
# getting the desired page number from url
page_number = request.GET.get('page')
try:
page_obj = p.get_page(page_number) # returns the desired page object
except PageNotAnInteger:
# if page_number is not an integer then assign the first page
page_obj = p.page(1)
except EmptyPage:
# if page is empty then return last page
page_obj = p.page(p.num_pages)
context = {'page_obj': page_obj}
# sending the page object to index.html
return render(request, 'index.html', context)
在第三行,分页器类被导入。在索引函数中,我们构造了一个叫做p的分页器对象。这个分页器创建页面对象。每个页面对象将有相同数量的帖子对象。然后我们从GET请求的查询参数’page’中检索出所需的页码。这个页码被用来提取正确的页面对象。
现在在index.html –
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django Paginator example</title>
</head>
<body>
<div class="container">
{% for post in page_obj.object_list %}
{# note that the list of posts are in the page_obj.object_list not page_obj #}
<h1>{{post.title}}</h1>
<small>{{post.author}}</small>
<p>{{post.content}}</p>
<hr/>
{% endfor %}
</div>
<center>
{%if page_obj.has_previous %} {# whether the previous page exists #}
<a href="?page={{page_obj.previous_page_number}}"><</a> {# link to the prev page #}
{% endif %}
<span>{{page_obj.number}}</span> {# the current page number #}
{%if page_obj.has_next %} {# whether the next page exists #}
<a href="?page={{page_obj.next_page_number}}">></a> {# link to the next page #}
{% endif %}
</center>
</body>
</html>
结果 :
在图片中,我们用GET请求发送了页码的值(用矩形表示)。你可以在图片的底部看到分页(用矩形标记)。
这里是最后一页的另一张图片–
方法: Paginator.get_page( page_number )
它接受一个数字参数,并返回一个具有给定的基于1的索引的页面对象。如果传递的参数不是一个数字,那么它返回第一页。如果页数是负数或大于页数的数字,那么它将返回最后一页。
如果页面的对象列表是空的,并且在Paginator对象中allow_empty_first_page被设置为false,则抛出EmptyPage错误。
Paginator.page(number)
:它也做同样的事情,但如果该数字的页面不存在,会引发InvalidPage错误。
属性:
Paginator.count | 返回所有页面中的对象总数。 |
---|---|
Paginator.num_pages | 返回总页数 |
Paginator.page_range | 返回一个基于1的范围迭代器 |
然而,由于Paginator类使用Page类来分配对象,如果我们对Page类有更多的了解,会更好。
页类:
一般来说,Page对象是在Paginator类中使用的。你很少需要手动构建它。
语法 :
page = Page( object_list , number, paginator)
这里object list是对象的列表,number参数用来给Page对象编号。Paginator是指构建此页面对象的Paginator对象。
属性:
Page.object_list | 返回对象的列表 |
---|---|
Page.number | 返回页面对象的编号 |
Page.paginator | 返回相应的分页器对象 |
方法:
Page.has_next() | 如果下一个Page对象退出则返回True,否则返回False。 |
---|---|
Page.has_previous() | 如果前一个Page对象退出则返回True,否则返回False。 |
Page.has_other_pages() | 如果有下一页或上一页,返回True。 |
Page.next_page_number() | 返回下一页的页码。如果下一页不存在,则提示InvalidPage。 |
Page.previous_page_number() | 返回前一页的页码。如果前一个页面不存在,则提示InvalidPage。 |
Page.start_index() | 返回页面上第一个对象的基于1的索引,相对于分页器列表中的所有对象。 |
Page.end_index() | 返回页面上最后一个对象的基于1的索引,相对于分页器列表中的所有对象。 |