ページネーション機能のコード
ページネーションのロジックとスタイル
from django.utils.safestring import mark_safe
from django.http.request import QueryDict
class PageNavigator:
"""
必要なパラメータ
page: 現在のページ番号 (必須)
total_items: 全データ数 (オプション)
items_per_page: 1ページあたりの表示アイテム数 (オプション)
max_pages: 最大表示ページ数 (オプション)
"""
def __init__(self, page, total_items, items_per_page=10, max_pages=11):
try:
self.page = int(page)
if self.page <= 0:
self.page = 1
except Exception:
self.page = 1
# 全データ数
total_items = total_items
# 1ページあたりの表示アイテム数
items_per_page = items_per_page
# 全ページ数
total_pages, remainder = divmod(total_items, items_per_page)
if remainder:
total_pages += 1
# 最大表示ページ数
half_max_pages = max_pages // 2
if total_pages <= max_pages:
page_start = 1
page_end = total_pages
else:
if self.page - half_max_pages <= 0:
page_start = 1
page_end = max_pages
elif self.page + half_max_pages > total_pages:
page_end = total_pages
page_start = total_pages - max_pages + 1
else:
page_start = self.page - half_max_pages
page_end = self.page + half_max_pages
self.page_start = page_start
self.page_end = page_end
self.total_pages = total_pages
self.start_index = (self.page - 1) * items_per_page
self.end_index = self.page * items_per_page
@property
def page_links(self):
links = []
if self.page == 1:
links.append('<li class="disabled"><a aria-label="Previous"> <span aria-hidden="true">«</span></a></li>')
else:
links.append('<li><a href="?page={}" aria-label="Previous"> <span aria-hidden="true">«</span></a></li>'.format(self.page - 1))
for i in range(self.page_start, self.page_end + 1):
if i == self.page:
links.append('<li class="active"><a href="?page={}">{}</a></li>'.format(i, i))
else:
links.append('<li><a href="?page={}">{}</a></li>'.format(i, i))
if self.page == self.total_pages:
links.append('<li class="disabled"><a aria-label="Next"> <span aria-hidden="true">»</span></a></li>')
else:
links.append('<li><a href="?page={}" aria-label="Next"> <span aria-hidden="true">»</span></a></li>'.format(self.page + 1))
return ''.join(links)
View での使用例
# 顧客リストの表示
class CustomerListView(View):
def get(self, request, *args, **kwargs):
query = self.search(["qq", "name", "phone"])
if request.path_info == reverse('customer_list'):
title = '共有顧客'
customers = models.Customer.objects.filter(query, consultant__isnull=True)
else:
title = '私の顧客'
customers = models.Customer.objects.filter(query, consultant=request.user_obj)
paginator = PageNavigator(request.GET.get('page', 1), customers.count(), 10, 3)
return render(request, 'consultant/customer_list.html', {
"customers": customers[paginator.start_index:paginator.end_index],
"page_links": paginator.page_links,
"title": title
})
HTML ページでの Bootstrap スタイルの適用
<script src="bootstrap-3.3.7/css/bootstrap.css"></script>
<nav aria-label="Page navigation">
<ul class="pagination">
{{ page_links }}
</ul>
</nav>