장고에는 페이지네이션을 구현할 수 있는 기능이 있다.
먼저, django shell을 통해 그 기능들을 확인해 본다.
$ python manage.py shell
현재 56개의 데이터가 있다.
>>> from django.core.paginator import Paginator
>>> from posts.models import Post
>>> posts = Post.objects.all()
>>> posts.count()
56
한 페이지에 6개의 데이터가 들어가도록 만든다.
>>> pages = Paginator(posts, 6)
<string>:1: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <class 'posts.models.Post'> QuerySet.
페이지 범위 확인하기
>>> pages.page_range
range(1, 11)
1번 페이지의 데이터 확인하기
>>> page = pages.page(1)
>>> page.object_list
<QuerySet [<Post: 제목이구나>, <Post: title_data_01>, <Post: title_data_02>, <Post: title_data_03>, <Post: 안녕하세요 클래스형 뷰입니다.>, <Post: 제네릭 뷰 제목>]>
현재 페이지의 다음 페이지 또는 이전 페이지가 있는지 확인하기
>>> page.has_next()
True
>>> page.has_previous()
False
>>> page.next_page_number()
2
views.py
def post_list(request):
posts = Post.objects.all()
paginator = Paginator(posts, 6)
curr_page_number = request.GET.get('page')
if curr_page_number is None: # 첫 번째 페이지일 경우 query string이 붙지 않는다.
curr_page_number = 1
page = paginator.page(curr_page_number)
return render(request, 'posts/post_list.html', {'page': page})
templates/posts/post_list.html
{% if page.object_list %}
<div class="post_container">
{% for post in page.object_list %}
<div class="post">
<a href={% url 'post-detail' post.id %}>
<h2 class="title">{{post.title}}</h2>
<p class="date">{{post.dt_created}}</p>
<p class="text">{{post.content|slice:":100"}}</p>
</a>
</div>
{% endfor %}
</div>
<div class="paginator">
{% if page.has_previous %}
<a href="?page=1" class="first">first</a>
<a href="?page={{ page.previous_number }}" class="prev">prev</a>
{% endif %}
<span>
<p>{{ page.number }} of {{ page.paginator.num_pages }}</p>
</span>
{% if page.has_next %}
<a href="?page={{ page.next_page_number }}" class="next">next</a>
<a href="?page={{ page.paginator.num_pages }}" class="last">last</a>
{% endif %}
</div>
{% else %}
<div class="blank">
<p>보여줄 글이 없어요.<br>첫 글을 작성해 보세요!</p>
</div>
{% endif %}