方法一:使用pure_pagination進行分頁
1. pure_pagination介紹
pure_pagination基于并且兼容django原生的pagination模塊。
2. 安裝pure_pagination
pip install django-pure-pagination
3. 配置
- 添加 pure_pagination 到 INSTALLED_APPS
INSTALLED_APPS = (
...
'pure_pagination',
)
A few settings can be set within settings.py
PAGINATION_SETTINGS = {
'PAGE_RANGE_DISPLAYED': 10,
'MARGIN_PAGES_DISPLAYED': 2,
'SHOW_FIRST_PAGE_WHEN_INVALID': True,
}
4. 代碼
- 視圖函數
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger
class IndexView(View):
def get(self, request):
# 文章列表
article_list = Article.objects.filter()
# 分頁數據
try:
page = int(request.GET.get('page', 1)) # 頁碼
paginator = Paginator(article_list, 10, request=request) # 獲取有多少頁
article_list = paginator.page(page) # 獲取指定頁的數據
except Exception as e:
return HttpResponseRedirect('/')
return render(request, 'index.html', {
'article_list': article_list
})
- 模板
<ul class="pagination">
{# 上一頁 #}
{% if article_list.has_previous %}
<li class="waves-effect"><a href="?page={{ article_list.previous_page_number.querystring }}"><i class="material-icons">chevron_left</i></a></li>
{% else %}
<li class="disabled"><a href="#!"><i class="material-icons">chevron_left</i></a></li>
{% endif %}
{% for page in article_list.pages %}
{% if page %}
{% ifequal page article_list.number %}
{# 當前頁頁 #}
<li class="active"><a>{{ page }}</a></li>
{% else %}
{# 指定頁 #}
<li class="waves-effect"><a href="?{{ page.querystring }}">{{ page }}</a></li>
{% endifequal %}
{% else %}
<li class="waves-effect"><a href="#">...</a></li>
{% endif %}
{% endfor %}
{# 下一頁 #}
{% if article_list.has_next %}
<li class="waves-effect"><a href="?page={{ article_list.next_page_number.querystring }}"><i class="material-icons">chevron_right</i></a></li>
{% else %}
<li class="disabled"><a href="#!"><i class="material-icons">chevron_right</i></a></li>
{% endif %}
方法二:使用django原生的分頁方法
使用原生的分頁方法要想實現一個比較好的結果需要使用templatetags,有點復雜,下面我們一點一點來
1. 首先建立模板標簽
app/
templatetags/
__init__.py
paginate_tags.py
2. 編碼
- 視圖函數
def question_index(request):
article_list = Article.objects
context = {
'article_list': article_list,
}
return render(request, 'app/index.html', context)
- paginate_tags
from django import template
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
register = template.Library()
// 這是定義模板標簽要用到的
@register.simple_tag(takes_context=True)
def paginate(context, object_list, page_count):
// context是Context 對象,object_list是你要分頁的對象,page_count表示每頁的數量
left = 3
right = 3
// 獲取分頁對象
paginator = Paginator(object_list, page_count)
// 從請求中獲取頁碼號
page = context['request'].GET.get('page')
try:
object_list = paginator.page(page) # 根據頁碼號獲取數據頁碼對象
context['current_page'] = int(page) # 將當前頁碼號封裝進context中
// 獲取頁碼列表
// pages = paginator.page_range
pages = get_left(context['current_page'], left, paginator.num_pages) + get_right(context['current_page'], right, paginator.num_pages)
except PageNotAnInteger:
object_list = paginator.page(1) # 獲取首頁數據頁碼對象
context['current_page'] = 1
// pages = paginator.page_range
pages = get_right(context['current_page'], right, paginator.num_pages)
except EmptyPage:
// 用戶傳遞的是一個空值,則把最后一頁返回給他
object_list = paginator.page(paginator.num_pages)
// num_pages為總分頁數
context['currten_page'] = paginator.num_pages
// pages = paginator.page_range
pages = get_left(context['current_page'], left, paginator.num_pages)
context['questions'] = object_list
context['pages'] = pages # 頁碼列表
context['last_page'] = paginator.num_pages
context['first_page'] = 1
// 用于判斷是否加入省略號
try:
context['pages_first'] = pages[0]
context['pages_last'] = pages[-1] + 1
except IndexError:
context['pages_first'] = 1
context['pages_last'] = 2
return ''
def get_left(current_page, left, num_pages):
"""
輔助函數,獲取當前頁碼的值得左邊兩個頁碼值,要注意一些細節,比如不夠兩個那么最左取到2
,為了方便處理,包含當前頁碼值,比如當前頁碼值為5,那么pages = [3,4,5]
"""
if current_page == 1:
return []
elif current_page == num_pages:
l = [i - 1 for i in range(current_page, current_page - left, -1) if i - 1 > 1]
l.sort()
return l
l = [i for i in range(current_page, current_page - left, -1) if i > 1]
l.sort()
return l
def get_right(current_page, right, num_pages):
"""
輔助函數,獲取當前頁碼的值得右邊兩個頁碼值,要注意一些細節,
比如不夠兩個那么最右取到最大頁碼值。不包含當前頁碼值。比如當前頁碼值為5,那么pages = [6,7]
"""
if current_page == num_pages:
return []
return [i + 1 for i in range(current_page, current_page + right - 1) if i < num_pages - 1]
- 模板
<ul class="pagination">
{# 判斷是否還有上一頁,確定是否激活上一頁按鈕 #}
{% if questions.has_previous %}
<li class="waves-effect"><a href="?page={{ questions.previous_page_number }}"><i class="material-icons">chevron_left</i></a></li>
{% else %}
<li class="disabled"><a href="#!"><i class="material-icons">chevron_left</i></a></li>
{% endif %}
{ # 永遠顯示第一頁 #}
{% if first_page == current_page %}
<li class="active"><a>1</a></li>
{% else %}
<li class="waves-effect"><a href="?page=1">1</a></li>
{% endif %}
{# 2以前的頁碼號要被顯示成省略號 #}
{% if pages_first > 2 %}
<li class="waves-effect"><a href="#">...</a></li>
{% endif %}
{% for page in pages %}
{% if page == current_page %}
<li class="active"><a>{{ page }}</a></li>
{% else %}
<li class="waves-effect"><a href="?page={{ page }}">{{ page }}</a></li>
{% endif %}
{% endfor %}
{# pages最后一個值+1的值小于最大頁碼號,說明有頁碼號需要被省略號替換 #}
{% if pages_last < last_page %}
<li class="waves-effect"><a href="#">...</a></li>
{% endif %}
{# 永遠顯示最后一頁的頁碼號,如果只有一頁則前面已經顯示了1就不用再顯示了 #}
{% if last_page != 1 %}
{% if last_page == current_page %}
<li class="active"><a>{{ last_page }}</a></li>
{% else %}
<li class="waves-effect"><a href="?page={{ last_page }}">{{ last_page }}</a></li>
{% endif %}
{% endif %}
{# 判斷是否還有下一頁,確定是否激活下一頁按鈕 #}
{% if questions.has_next %}
<li class="waves-effect"><a href="?page={{ questions.next_page_number }}"><i class="material-icons">chevron_right</i></a></li>
{% else %}
<li class="disabled"><a href="#!"><i class="material-icons">chevron_right</i></a></li>
{% endif %}
</ul>
3. 使用
{% load paginate_tags %}
{% paginate article_list 3 %} # 對應模板標簽中的函數paginate(context, object_list, page_count),context是默認傳入的,article_list代表object_list,3代表每頁的數量
{% for article in article_list %}
<section class="post">
<h1>{{ article.title }}</h1>
<p>{{ article.content }}</p>
...
</section>
{% include 'pagination.html' %}