본문 바로가기
  • 실행력이 모든걸 결정한다
Django

[Django] 제네릭 뷰의 페이징 기능

by 김코더 김주역 2023. 2. 15.
반응형

화면에 표시할 레코드가 많은 경우에 페이지마다 나눠서 보여줄 수 있도록 하는 기능을 페이징 또는 페이지네이션이라고 한다. 이번 포스팅에서는 제네릭 뷰에서 제공하는 페이징 기능을 알아보도록 하자.

 

1. 페이징 기능 활성화하기

- 페이징 기능은 MultipleObjectMixin의 paginate_by 속성을 지정함으로써 활성화 가능하다. ListView와 날짜 기반 제네릭 뷰는 MultipleObjectMixin을 상속받고 있기 때문에 페이징이 가능한 것이다.

- 장고의 페이징 기능이 활성화되면 객체 리스트에는 페이지별로 구분되어 저장된다. 즉, 디폴트 context 변수인 object_list에는 특정 페이지에 해당하는 객체만 담긴다.

- paginate_by 속성에는 페이지당 몇 개의 항목을 출력할지 정수로 지정한다.

 

 

 

2. 페이지 번호 지정

아래에 소개된 2가지 방법 중에서 하나를 선택하면 된다.

 

1) URL의 요청 파라미터 page로 전달

?page=3

 

2) URLconf의 <int:page>를 통해 page 파라미터를 전달

path('posts/page<int:page>/', PostLV.as_view()),

 

참고로, 파라미터의 이름을 page가 아닌 다른 것으로 쓰려면 뷰의 page_kwargs 속성으로 알려줘야 한다.

 

 

 

3. 템플릿 파일에서 사용되는 context 변수

  • object_list : 특정 페이지에 해당되는 객체들만 담겨있음
  • is_paginated : 페이징 적용 여부
  • paginator : django.core.paginator.Paginator 클래스의 객체 ([4. Paginator] 참고)
  • page_obj : django.core.paginator.Page 클래스의 객체 ([5. Page] 참고)

※ 페이징 처리가 안되는 경우에는 paginator, page_obj 값은 None을 가지게 된다.

 

 

 

4. Paginator

- 전체 페이지를 담당하며, 특정 페이지 객체인 django.core.paginator.Page 객체를 생성한다.

 

1) 인자

class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)

- object_list : 페이징 대상인 전체 객체 리스트다. 리스트, 튜플, QuerySet 타입이 올 수 있다.

- per_page : 페이지당 최대 항목 수

- orphans : 마지막 페이지에 넣을 수 있는 항목의 최소 개수로, 디폴트 값은 0이다. 마지막 페이지의 항목 개수가 orphans 값보다 작다면 per_page 값과 상관없이 그 이전 페이지에 강제로 포함시킨다.

- allow_empty_first_page : 첫 페이지의 항목 개수가 0임을 허용하는지의 여부다. False 값을 가진다면 첫 페이지의 항목 개수가 0일 때 EmptyPage 에러가 발생한다.

 

 

2) 메소드

- page(n) : n번째 페이지에 대한 Page 객체를 반환한다. n은 1부터 시작하며, 해당 페이지가 존재하지 않으면 InvaildPage 에러가 발생한다.

- get_page(n) : n번째 페이지에 대한 Page 객체를 반환한다. n은 1부터 시작하며, 인자가 음수이거나 최대 페이지 숫자보다 크면 마지막 페이지로 처리되고, 인자가 숫자가 아니면 첫 페이지로 처리된다.

 

 

3) 속성

- count : 항목의 총 개수

- num_pages : 페이지의 총 개수

- page_range : 1부터 시작하는 페이지의 범위 리스트

 

 

 

5. Page

- Paginator 객체에 의해 생성되는 특정 페이지에 대한 객체다.

 

1) 인자

class Page(object_list, number, paginator)

- object_list : Paginator의 object_list와 동일함

- number : 몇 번째 페이지인지를 나타냄

- paginator : Page를 생성해주는 Paginator 객체

 

 

2) 메소드

- has_next() : 다음 페이지의 존재 여부

- has_previous() : 이전 페이지의 존재 여부

- has_other_pages() : 다음 페이지 또는 이전 페이지의 존재 여부

- next_page_number() : 다음 페이지 번호 (다음 페이지가 유효하지 않다면  InvalidPage 에러 발생)

- previous_page_number() : 이전 페이지 번호 (이전 페이지가 유효하지 않다면 InvalidPage 에러 발생)

- start_index() : 현재 페이지 첫 번째 항목의 전체 기준 인덱스를 반환 (1부터 시작)

- end_index() : 현재 페이지 마지막 항목의 전체 기준 인덱스를 반환 (1부터 시작)

 

 

3) 속성

- object_list : 현재 페이지에 대한 객체 리스트

- number : 1부터 시작하는 현재 페이지의 번호

- paginator : 현재 Page를 생성해준 Paginator 객체

 

 

 

6. 템플릿 코드에 적용

현재 페이지를 표시하거나 페이지를 바꾸기 위한 nav는 다음과 같이 작성할 수 있다. page라는 요청 파라미터를 통해 페이지 전환이 이루어지도록 <a>의 href를 지정했다. 그리고 첫 페이지면 Previous 버튼을 비활성화했고, 마지막 페이지면 Next 버튼을 비활성화했다.

<nav aria-label="Page navigation example">
    <ul class="pagination justify-content-center">
    {% if page_obj.has_previous %}
        <li class="page-item">
            <a href="?page={{ page_obj.previous_page_number }}" class="page-link">Previous</a>
        </li>
    {% else %}
        <li class="page-item disabled">
            <a class="page-link">Previous</a>
        </li>
    {% endif %}
        <li class="ms-3 me-3 mt-1"><span class="align-middle">Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span></li>
    {% if page_obj.has_next %}
        <li class="page-item">
            <a href="?page={{ page_obj.next_page_number }}" class="page-link">Next</a>
        </li>
    {% else %}
        <li class="page-item disabled">
            <a class="page-link">Next</a>
        </li>
    {% endif %}
    </ul>
</nav>

화면 출력 내용은 다음과 유사하게 나올 것이다.

 

반응형

댓글