- Published on
[Django4] Paginator 사용법
- Authors
- Name
- Almer Minified
[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값으로 반환한다.