Today I Learned/django

장고 (django) pagination 구현하기

하나719 2023. 7. 19. 11:21
반응형

장고 페이지네이션 구현 django pagination

1. views.py 

Paginator 클래스 활용

from django.core.paginator import Paginator

def post_list(request):
    post_list = Post.published.all() # 게시된 게시물 목록
    paginator = Paginator(post_list, 3)
    page_number = request.GET.get('page', 1)
    posts = paginator.page(page_number)
    return render(request, 'blog/post/list.html', {'posts':posts})
  • paginator = Paginator(리스트, 한 페이지에 보여질 갯수) -> 전체 게시물을 불러오고, 한 페이지에 몇개씩 보여줄지 설정해서 페이지마다 어떤 게시물이 몇개씩 보여질지 만들어줌
  • page_number = request.GET.get('page',1) : 몇번째 페이지를 유저가 클릭했는지 요청을 통해 가져와서 전달하고 defalut는 1로 첫번째 페이지를 전달한다.
  • paginator.page(page_number) ->  위에 만들어준 두가지를 조합해서 템플릿에 전달할 context를 구성 
    • 전체 게시물 리스트에서 요청받은 페이지에 있는 게시물을 전달해줌

2. pagination.html 

templates경로 아래에 pagination.html 파일을 만들어준다.

<div class="pagination">
    <span class="step-links">
    {% if page.has_previous %}
        <a href="?page={{ page.previous_page_number }}">Previous</a>
    {% endif %}
    <span class="current">
        Page {{ page.number }} of {{ page.paginator.num_pages }}.
    </span>
    {% if page.has_next %}
        <a href="?page={{ page.next_page_number }}">Next</a>
    {% endif %}
    </span>
</div>
  • page.has_previous: 이전 페이지가 있는지 검사 
    • page.previous_page_number :이전 페이지 
  • page.has_next: 다음 페이지가 있는지 검사 
    • page.next_page_number: 다음 페이지 
  • page.number: 현재 페이지 
  • page.paginator.num_pages: 전체 페이지 수 

3. list.html 

페이지네이션을 보여줄 리스트 템플릿에 추가

{% extends "blog/base.html" %}
{% block title%} My Blog {% endblock title%}
{% block content %}
    <h1>My Blog</h1>
    {% for post in posts %}
        <h2>
            <a href="{{ post.get_absolute_url }}">
                {{ post.title }}
            </a>
        </h2>
        <p class="date">
            Published {{post.publish}} by {{post.author}}
        </p>
        {{post.body|truncatewords:30|linebreaks }}
    {% endfor %}
    {% include "pagination.html" with page=posts %}
{% endblock content%}
  • {% include "pagination.html with page = posts %}
    • include: 위에 만들어준 pagination.html을 불러와서 아래 붙여준다.
    • with: pagination.html 에 사용되는 page 에 views에서 만들어준 객체 posts를 전달 

4. 에러 예외처리 추가

지금 페이지가 2번째 까지 밖에 없기 때문에, url에 직접 3을 입력해서 세번째 페이지를 요청하면 에러가 발생한다. 

따라서 존재하지 않는 페이지를 요청할 때 예외처리를 통해 마지막 페이지로 이동할 수 있도록 변경해주는 작업을 추가한다. 

 

views.py

    from django.core.paginator import Paginator, EmptyPage
    
    def post_list(request):
    .... #생략
     
   	try:
    	posts = paginator.page(page_number)
    except EmptyPage:
    	posts = paginator.page(paginator.num_pages)
  • 위에 만들었던 views.py 의 post_list 함수에서 변경된 부분만 작성했습니다.
    • EmptyPage 클래스를 import
    • 원래 작성해두었던 정상적인 케이스를 try에 그대로 넣어줌
    • EmptyPage일때 예외처리 작성해줌
      • paginator.num_pages -> 전체 페이지 수 = 마지막 페이지 

page = 3으로 요청했는데 에러가 발생하지 않고 마지막 페이지로 랜딩시켜줌

결과물 

  • 한 페이지에 3개씩 출력
  • 총 4개 글

반응형