Published on

[Django4] Paginator 사용법

Authors
  • avatar
    Name
    Almer Minified
    Twitter

[Django4] Paginator 사용법

페이지네이터란?

장고에서 페이지네이터는 사용자로 하여금 쉽게 쿼리셋을 리스트화 해서 페이지에 따라 조작할 수 있게 도와준다. 페이지네이터를 잘 활용하면 쉽게 무언가를 불러올 수 있으며 전체 쿼리셋의 정보도 알 수 있다. 실은 자신이 커스터마이징 하거나 따로 페이지네이션을 구현해도 되지만 소규모 프로젝트에선 그렇게 문제가 없으니 페이지네이터를 쓰는 것이 효율적이다.

기본적인 사용법

페이지네이터의 기본 코드는 다음과 같다.

  queryset = Post.objects.filter(your_query) paginator =
  Paginator(queryset, items_per_page) posts =
  paginator.page(page_number).object_list num_pages = paginator.num_pages
  page_number = page_number
코드요약 실은 이정도만 알면 거의 모든 것이 해결이 가능하다. 하나하나 차근차근 알아보도록 하자.

queryset에 대해

queryset = Post.objects.filter(your_query)

쿼리셋은 장고에서 주는 쿼리셋을 그대로 사용하면 된다. 쿼리셋을 지정한다고 해서 바로 쿼리가 실행되는 것은 아니고 후에 object_list 등의 실제 값이 필요한 경우에 실행된다. 보통 데이터가 많이 쌓일수록 확인해야 하는 테이블의 수가 많기 때문에 페이지네이터를 쓰면 쿼리셋을 쉽게 다룰 수 있다.

paginator에 대해

paginator = Paginator(queryset, items_per_page)

이 부분은 쿼리셋을 한 페이지에 몇 개의 아이템을 가져올지 지정하면서 설정하는 부분이다. 즉 페이지네이터 객체를 만들어내는 부분인데, 쿼리셋과 한 페이지 당 몇 개의 아이템을 가져올지 지정해줘야 한다는 것을 명심하자. 이 부분에서 items_per_page값을 무엇으로 하느냐에 따라 뒤의 num_pages가 달라지게 된다. 또한 page(page_number)값 역시 달라지게 된다.

items_per_page 값에 따른 결과 변화

만약 쿼리셋 안에 들어온 객체가 100개라고 해보자. 그렇다면 items_per_page를 10개로 하면 10개의 페이지가 생기므로 그 외에 페이지 숫자를 입력하게 되면 다른 연산에서 오류가 발생한다 그것도 마찬가지고 num_pages도 달라지게 된다. 100/10 은 10이므로 10개의 페이지가 생기게 되는 것이다. 만약 items_per_page를 1000으로 하게 되면 1개의 페이지만 생성된다.

.page().object_list에 대해

posts = paginator.page(page_number).object_list

이 부분은 페이지네이터 객체에서 어떤 페이지를 가져온 후 그 페이지에서 쿼리셋을 추출해내겠다는 의미이다. object_list가 object_list()가 아님을 유의해야한다. 또한 여기서 페이지네이터 객체에서 가져올 수 없는 page_number를 입력하게 되면 오류가 발생한다. 이 오류를 위해 try ~ except 구문을 통해 새로 설정해주면 된다. 무조건 페이지 1은 반환하게 되니까 그 경우 보통 1페이지를 참조하도록 설정한다. 여기선 쿼리셋이 추출된다는 것을 기억해두자.

num_pages에 대해

num_pages = paginator.num_pages

이 부분은 페이지네이터 객체에 포함된 페이지들의 수가 몇개인지 알려준다. 위에서 100개의 객체를 가졌을 경우 10개씩만 나누면 총 10개의 페이지가 나오게 되는데 이 부분을 말한 것이다. number of pages라고 기억하면 좋다.

num_pages에 대해

num_pages = paginator.num_pages

이 부분은 페이지네이터 객체에 포함된 페이지들의 수가 몇개인지 알려준다. 위에서 100개의 객체를 가졌을 경우 10개씩만 나누면 총 10개의 페이지가 나오게 되는데 이 부분을 말한 것이다. number of pages라고 기억하면 좋다.

실전 예제

이번 예제에선 장고의 템플릿 태그를 활용하는 방안을 알아보자.

{% for post in page_obj %}
<div>
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
</div>
{% endfor %}

    <div class="pagination">
        <span class="your_class">
            {% if page_obj.has_previous %}
                <a href="?page=1">첫 페이지</a>
                <a href="?page={{ page_obj.previous_page_number }}">이전</a>
            {% endif %}

            <span class="current">
                페이지 {{ page_obj.number }} / {{ 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 %}
        </span>
    </div>

코드 자세히 보기

이 코드에서 중요한 것은 next_page_number, previous_page_umber 이 두 부분이다. 위에서 설명한 적이 없지만 말 그대로 이전 페이지와 다음 페이지의 번호를 반환한다. 물론 has_previous와 has_next와 함께 사용해주면 오류도 방지할 수 있다. 이 옵션들 역시 말 그대로 previous페이지를 가지고 있는가 next페이지를 가지고 있는가를 boolean값으로 반환한다.