# Pagination
>以下代码摘自 Django 官方文档
[Django Pagination 的官方文档](https://docs.djangoproject.com/en/2.0/topics/pagination/)
Django 提供了几个类, 可以帮助您管理分页数据 - 也就是说,通过 "上一个 / 下一个" 链接分割多个页面的数据, 这些类放在 `django/core/ paginator.py`中。
## 例子
```
>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2) # 2 条数据为一页, 实例化分页对象
>>> p.count # 对象一共 4 个元素
4
>>> p.num_pages # 对象分为 4 页
2
>>> type(p.page_range) # 类型
<class 'range'>
>>> p.page_range # 对象页的可迭代范围
range(1, 3)
>>> page1 = p.page(1) # 取对象的第一分页对象
>>> page1 # 第一页分页对象的元素列表
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']
>>> page2 = p.page(2) # 取对象的第二页分页对象
>>> page2.object_list # 第二页分页对象的元素列表
['george', 'ringo']
>>> page2.has_next() # 第二页分页对象有下一页对象吗
False
>>> page2.has_previous() # 第二页分页对象是否还有前一页
True
>>> page2.has_other_pages() # 第二页分页对象是否还有其他页
True
>>> page2.nex_page_number() # 第二页分页对象下一页的页码, 因为没了, 所以报错
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Page' object has no attribute 'nex_page_number'
>>> page2.previous_page_number() # 第二页分页对象的上一页码值
1
>>> page2.start_index() # 第二页分页对象开始的索引
3
>>> page2.end_index() # 第二页分页对象结束的索引
4
>>> page1.start_index() # 第一页分页对象开始的索引, 注意: 索引是从 1 开始的
1
>>> page1.end_index() # 第一页分页对象开始的索引
```
## 在视图中使用 Paginator
下面是视图代码:
```
from django.shortcuts import render
from django.http import HttpResponse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import HeroInfo
def listing(request):
hero_list = HeroInfo.objects.all()
paginator = Paginator(hero_list, 5) # 每页显示五个元素
page = request.GET.get('page')
try:
heros = paginator.page(page)
except PageNotAnInteger: # 如果页码不是整数, 则显示第一页
heros = paginator.page(1)
except EmptyPage: # 如果页码超出范围, 则显示最后一页
heros = paginator.page(paginator.num_pages)
return render(request, 'herolist.html', {'heros': heros})
```
html 代码:
不过这里还有个 bug, 就是在最后一页的时候, 点击上一页, 显示的确是第一页的内容.
```
{% load static %}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hero</title>
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
{#遍历hero列表, 显示元素信息 #}
<ul>
{% for hero in heros %}
<li>{{ hero.name }}</li>
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if heros.has_previous %} {# 判断是否还有上一页 #}
<a href="?page=1">« 第一页</a>
<a href="?page{{ heros.previous_page_number }}">上一页</a>
{% endif %}
<span class="current">
Page {{ heros.number }} of {{ heros.paginator.num_pages }}.
</span>
{% if heros.has_next %}
<a href="?page={{ heros.next_page_number }}">下一页</a>
<a href="?page={{ heros.paginator.num_pages }}">最后 «</a>
{% endif %}
</span>
</div>
</body>
</html>
```
urls 代码:
```
from django.conf.urls import url
from booktest import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^listing/$', views.listing, name='listing'),
]
```
大概就是这么个效果:
![分页效果1](https://i.imgur.com/o99cd5z.png)
![分页效果2](https://i.imgur.com/CXou49N.png)
![分页效果3](https://i.imgur.com/ChfyqSL.png)
>以下代码摘自 Django 官方文档
[Django Pagination 的官方文档](https://docs.djangoproject.com/en/2.0/topics/pagination/)
Django 提供了几个类, 可以帮助您管理分页数据 - 也就是说,通过 "上一个 / 下一个" 链接分割多个页面的数据, 这些类放在 `django/core/ paginator.py`中。
## 例子
```
>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2) # 2 条数据为一页, 实例化分页对象
>>> p.count # 对象一共 4 个元素
4
>>> p.num_pages # 对象分为 4 页
2
>>> type(p.page_range) # 类型
<class 'range'>
>>> p.page_range # 对象页的可迭代范围
range(1, 3)
>>> page1 = p.page(1) # 取对象的第一分页对象
>>> page1 # 第一页分页对象的元素列表
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']
>>> page2 = p.page(2) # 取对象的第二页分页对象
>>> page2.object_list # 第二页分页对象的元素列表
['george', 'ringo']
>>> page2.has_next() # 第二页分页对象有下一页对象吗
False
>>> page2.has_previous() # 第二页分页对象是否还有前一页
True
>>> page2.has_other_pages() # 第二页分页对象是否还有其他页
True
>>> page2.nex_page_number() # 第二页分页对象下一页的页码, 因为没了, 所以报错
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Page' object has no attribute 'nex_page_number'
>>> page2.previous_page_number() # 第二页分页对象的上一页码值
1
>>> page2.start_index() # 第二页分页对象开始的索引
3
>>> page2.end_index() # 第二页分页对象结束的索引
4
>>> page1.start_index() # 第一页分页对象开始的索引, 注意: 索引是从 1 开始的
1
>>> page1.end_index() # 第一页分页对象开始的索引
```
## 在视图中使用 Paginator
下面是视图代码:
```
from django.shortcuts import render
from django.http import HttpResponse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import HeroInfo
def listing(request):
hero_list = HeroInfo.objects.all()
paginator = Paginator(hero_list, 5) # 每页显示五个元素
page = request.GET.get('page')
try:
heros = paginator.page(page)
except PageNotAnInteger: # 如果页码不是整数, 则显示第一页
heros = paginator.page(1)
except EmptyPage: # 如果页码超出范围, 则显示最后一页
heros = paginator.page(paginator.num_pages)
return render(request, 'herolist.html', {'heros': heros})
```
html 代码:
不过这里还有个 bug, 就是在最后一页的时候, 点击上一页, 显示的确是第一页的内容.
```
{% load static %}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hero</title>
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
{#遍历hero列表, 显示元素信息 #}
<ul>
{% for hero in heros %}
<li>{{ hero.name }}</li>
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if heros.has_previous %} {# 判断是否还有上一页 #}
<a href="?page=1">« 第一页</a>
<a href="?page{{ heros.previous_page_number }}">上一页</a>
{% endif %}
<span class="current">
Page {{ heros.number }} of {{ heros.paginator.num_pages }}.
</span>
{% if heros.has_next %}
<a href="?page={{ heros.next_page_number }}">下一页</a>
<a href="?page={{ heros.paginator.num_pages }}">最后 «</a>
{% endif %}
</span>
</div>
</body>
</html>
```
urls 代码:
```
from django.conf.urls import url
from booktest import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^listing/$', views.listing, name='listing'),
]
```
大概就是这么个效果:
![分页效果1](https://i.imgur.com/o99cd5z.png)
![分页效果2](https://i.imgur.com/CXou49N.png)
![分页效果3](https://i.imgur.com/ChfyqSL.png)