Django에서 제공하는 Paginator를 이용하여 게시판이나 리스트를 조회하는 모듈에 페이징을 적용 시킬수 있습니다.
페이징을 여러 view에 편리하게 적용시키기 위해 lib.py를 통해 PaginatorManager라는 함수를 정의하였습니다.
Paginator를 이용한 PaginatorManager 함수 구현
#lib.py
from django.core.paginator import Paginator
def PaginatorManager(request, queryset):
page = request.GET.get('page', 1)
paginator = Paginator(queryset, 20)
max_index = len(paginator.page_range)
current_page = int(page) if page else 1
page_numbers_range = 5 # Display only 5 page numbers
start_index = int((current_page - 1) / page_numbers_range) * page_numbers_range
end_index = start_index + page_numbers_range
if end_index >= max_index:
end_index = max_index
page_range = paginator.page_range[start_index:end_index]
print(start_index,end_index)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
return page_range, queryset
정의된 함수는 request 객체와 queryset을 인자로 받습니다. 함수 첫째 줄에서 인자로 받은 request 객체의 'page' 값을 가져옵니다. 이때 값이 없다면 1을 return 받습니다. 다음 Paginator(queryset , 20) 함수를 통해 paginator 객체를 생성합니다. Paginator는 장고에서 제공하는 함수로 queryset과 페이지당 보여줄 객체의 수를 인자로 받습니다. 여기서는 페이지당 20개의 게시물을 보여주기 위해 20을 인자로 사용했습니다.
paginator.page_range를 통해 querryset과 게시물을 보여주기 위한 인자 값을 기반으로 page 범위를 return 받습니다. 그리고 max_index에 그 range 길이 값을 저장합니다.
current_page는 현재 보고있는 page입니다. current_page 변수에 page 변수가 존재하면 page를 정수형으로 형변환 합니다. 없다면 1을 current_page에 할당합니다. 또한 page_number_range 변수는 화면에 보여줄 page index의 수를 보여줍니다.
start_index와 end_index는 화면에 보여줄 index의 시작과 끝 값을 나타냅니다. current_page와 page_number_range를 통해 구해줍니다.
만약 end_index가 max_index보다 크다면 end_index는 max_index가 되어야 하기 때문에 그 값을 대입합니다.
다음, 화면에 보여줄 최대 5개의 index의 값을 지정하기 위해, page_range에 paginator.page_range[start_index:end_index]와 같이 처음과 끝 인덱스를 슬라이스로 지정해주어 page_range에 대입합니다.
try구문에서 paginator.page(page) 통해 인자로 받은 page에 해당하는 페이지의 object를 querryset을 변환하여 가져옵니다. paginator.get_page(page)도 사용이 가능한데, 어떤 차이점이 있는지는 잘 알지 못하겠습니다. 혹시 아시는 분이 있다면 댓글 부탁드립니다 :)
views.py 에서 사용하기
#views.py
from django.views.generic import ListView
from board.forms import BoardForm
from lib import PaginatorManager
class BoardList(ListView):
def get_queryset(self):
queryset = Board.objects.filter(active=1).all()
return queryset
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PersonnelInfo, self).get_context_data(**kwargs)
context['page_range'], context['contacts'] = PaginatorManager(self.request, self.get_queryset())
context['form'] = BoardForm()
return context
PaginatorManger(self.request, self.get_queryset()) 을 통해 앞서 구현한 PaginatorManger 함수를 호출해줍니다. 그러면 return 값을 통해 화면에 보여줄 page_range와 querryset을 넘겨주고 이를 context를 통해 template로 넘겨줍니다.
template
<div class="row no-gutters d-flex justify-content-center">
<ul class="pagination">
{% if contacts.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1">« 처음</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ contacts.previous_page_number }}">이전</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">« 처음</a>
</li>
<li class="page-item disabled">
<a class="page-link" href="#">이전</a>
</li>
{% endif %}
{% for page in page_range %}
<li class="page-item {% if contacts.number == page %}active{% endif %}">
<a class="page-link" href="?page={{ page }}">{{ page }}</a>
</li>
{% endfor %}
{% if contacts.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ contacts.next_page_number }}">다음</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ contacts.paginator.num_pages }}">마지막 »</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">다음</a>
</li>
<li class="page-item disabled">
<a class="page-link" href="#">마지막 »</a>
</li>
{% endif %}
</ul>
</div>
views.py에서 넘겨준 context값을 통해 template의 페이징을 구현하였습니다.
bootstrap을 적용하였고, 다음과 같이 화면에 나타며 정상적으로 기능이 동작하는것을 확인할수 있었습니다.
'개발 > Web 개발' 카테고리의 다른 글
[Django] urls.py에서 (?P<pk>\d+)$ (0) | 2020.11.17 |
---|---|
[Javascript] 입력 필드,입력 폼에 세자리 마다 콤마(,) 표시 (0) | 2020.11.04 |
[Django] Ajax와 Django(python)을 이용한 엑셀 업로드 기능 구현 (0) | 2020.10.27 |
[Django] RuntimeError: crypgraphy is required (0) | 2020.10.22 |
[Django] Migration 오류 해결 방법 (migrate error) (0) | 2020.09.23 |