장고:페이징(페이지나누기)
장고! 웹 프레임워크! 틀:장고
개요
글쓰기에서 작성된 글 리스트를 만들 수 있었다. 일반적인 게시판에선 10, 20개 단위로 글들을 페이징 처리해 두는데, 이 기능이 쉽진 않아 글쓰기와 다른 목차로 떨어뜨려 작성한다.
방법
view 편집
글 목록을 보여주는 view를 다음과 같은 형태로 편집한다.
from django.core.paginator import Paginator #장고엔 다 있다!!
def list(request):
question_list = Question.objects.order_by('-create_date')
################## 페이징처리#########
page = request.GET.get('page', '1') #어떤 페이지를 보고 있을지 전달받는다. 전달되는게 없으면 기본적으로 1을받는다는 의미. 추후 탬플릿에서 구현.
paginator = Paginator(question_list, 10) # 페이지당 10개씩 보여주겠다는 의미.
question_list = paginator.get_page(page) #page에 담긴 페이지에 해당하는 리스트를 담는다.
context = {'question_list': question_list} #기존의 리스트 대신 페이지객체를 보낸다.
# ---------------------------------------------------------------------------------------- #
return render(request, 'list.html', context)
paginator의 속성을 page_obj(question_list)에 담아 보냈는데, paginator엔 몇몇 속성이 있다.
속성 | 설명 |
---|---|
paginator.per_page | 페이지당 보여줄 건수 |
number | 현재페이지 번호 |
num_pages | 전체 페이지 갯수 |
paginator.page_range | 페이지 범위. range(시작페이지, 끝페이지) 형태로 얻어진다. |
has_previous | 이전페이지 존재여부 |
previous_page_number | 이전페이지 번호 |
has_next | 다음페이지 존재여부 |
next_page_number | 다음페이지 번호 |
이외에도 좀 많다; 자세한 것은 공식 튜토리얼 참조 https://docs.djangoproject.com/ko/3.0/topics/pagination/
제네릭 뷰를 사용하는 경우엔 ListView 안에 paginate_by = 숫자
를 추가한다. 제네릭뷰에선 탬플릿에 page_obj 라는 이름으로 전달된다.
template 편집
기본적으로 최근 10개의 글만 볼 수 있게 되었다. 다음 글들을 보기 위해선 view에 page 인자를 전달해야 하는데, 이 전달을 위한 페이지 번호매기기가 필요하다.
역시나, 부트스트랩을 이용하면 간결하면서 이쁘게 만들 수 있다.
과정 | template |
---|---|
전체 틀 | div 안에 페이징처리에 들어갈 요소들을 담으면 편하다.<ui class="pagination">
...내용은 여기에
</ui>
|
이전페이지 버튼 만들기 | 앞번호와 처음링크.
위의 예시를 따른다면 page_obj 대신 question_list를 사용해야 한다. 이름 틀리지 않게 유의.{% if page_obj.has_previous %}
<a href="?page=1">처음으로</a>
<a href="?page={{ page_obj.previous_page_number }}">이전</a>
{% endif %}
이후 html이나 부트스트랩 따위를 이용해 내용을 꾸며주면 된다. <li class="page-item"> 따위로. |
페이지리스트 만들기 | 현재 페이지는 구분이 되게 표시를 해준다.<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
|
다음페이지 버튼 만들기 | 다음번호와 끝링크. 위에서와 동일하다.{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">다음</a>
<a href="?page={{ page_obj.paginator.num_pages }}">끝으로</a>
{% endif %}
이후 html이나 부트스트랩 따위를 이용해 내용을 꾸며주면 된다. |
얖옆으로 일정 개수의 페이지를 나타내고 싶은 경우
현재 페이지번호보다 5 작고, 5 큰 페이지까지 이동링크를 만들고 싶은 경우. 굉장히 다양한 방법이 있지만, 파이썬을 적극 활용해보자.
view에서 현재페이지를 얻은 후 앞뒤로 숫자 list를 만들어 template로 보낸다. 탬플릿의 '페이지리스트만들기'를 수정한다.
view에서 다음과 같이 보여줄 페이지를 정해 탬플릿으로 보낸다.
current_page_num=int(page)#현재 페이지는 몇인가?
first_page=1#첫 페이지 넘버
last_page=int(paginator.num_pages) #마지막페이지는 몇인가?
left_show =current_page_num - 5 #왼쪽으로 5개까지 나타낸다.
right_show =current_page_num + 5#우측으로 5개까지 나타낸다.
if current_page_num < 6:
left_show=first_page
if current_page_num+5 > last_page:
right_show = last_page
page_list = range(left_show, right_show+1) # 보여줄 페이지의 범위.
context = {'question_list': question_list,#기존의 리스트 대신 페이지객체를 보낸다.
'page_list':page_list} #보여줄 페이지 리스트
탬플릿은 다음과 같이 고친다.
{% for page_number in page_list %}
{% if page_number == question_list.number %}
<li class="page-item active" aria-current="page">
<a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
</li>
{% endif %}
{% endfor %}