python/Django

[Django] 12. 게시판 페이징 기능추가

끼발자 2021. 12. 29. 15:59
반응형

지금이야 게시글 개수가 몇개 없지만, 늘어난다면 어떻게 될까?

 

장고 쉘을 이용해서 게시글 개수를 늘려보자.

 

>>python manage.py shell

from pybo.models import Question
from django.utils import timezone
for i in range(300):
	q = Question(subject='%03d 게시글'%i, content = '약오르지', create_date = timezone.now())
	q.save()

 

페이징을 하지 않았으므로 스크롤이 굉장히 길어진다. 이제 페이징을 통해 화면을 개선해보자.

 

from django.core.paginator import Paginator
...
...
def index(request):
    '''
    pybo 목록 출력
    '''
    page = request.GET.get('page',1)  # 페이지 / GET방식으로 page를 파라미터로 가져올 때 사용, 파라미터 없이 들어올 때 dafault값을 1로 줌.

    # 조회
    question_list = Question.objects.order_by('-create_date') # -로 역순

    # 페이징
    paginator = Paginator(question_list,10)  # 한 페이지당 개수
    page_obj = paginator.get_page(page)

    context = {'question_list':page_obj}
    # return HttpResponse('Hi pybo') # Hi pybo를 response해라
    return render(request,'pybo/question_list.html',context)

 

장고에서 지원하는 페이지네이터를 불러오고 request.GET.get(  )을 이용해서 get 으로 전달되는 파라미터를 통해 보여줄 페이지를 결정하자.

 

url은 localhost:8000/pybo/?page=1 이렇게 기본값을 줄 수 있다.

 

paginator를 통해서 question_list를 10개로 자르고, url에서 받아온 page를 통해서 해당 페이지의 객체를 반환한다.

 

이제 보기 좋게 10개씩 끊어진 데이터를 볼 수 있다.

 

이제 페이지 이동기능을 추가하자.

 

책에선 여러 단계로 진행했지만, 한번에 진행하자.

...
</table>
<!--    페이징 시작-->
    <ul class="pagination justify-content-center">
<!--        이전 페이지-->
        {% if question_list.has_previous %}
        <li class="page-item">
            <a class="page-link"
               href="?page=1">
                처음
            </a>
        </li>
        <li class="page-item">
            <a class="page-link"
               href="?page={{ question_list.previous_page_number }}">
                이전
            </a>
        </li>
        {% else %}
        <li class="page-item disabled">
            <a class="page-link" tabindex="-1" aria-disabled="true" href="#">
                이전
            </a>
        </li>
        {% endif %}
<!--        페이지 리스트-->
        {% for page_number in question_list.paginator.page_range %}
        {% if page_number >= question_list.number|add:-5 and page_number <= question_list.number|add:5 %}
        {% if page_number == question_list.number %}
        <li class="page-item active" aria-current="page">
            <a class="page-link" href="?page={{ page_number }}">
                {{ page_number }}
            </a>
        </li>
        {% else %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_number }}">
                {{ page_number }}
            </a>
        </li>
        {% endif %}
        {% endif %}
        {% endfor %}
<!--        다음 페이지-->
        {% if question_list.has_next %}
        <li class="page-item">
            <a class="page-link"
               href="?page={{ question_list.next_page_number }}">
                다음
            </a>
        </li>
        <li class="page-item">
            <a class="page-link"
               href="?page={{ question_list.paginator.num_pages }}">
                마지막
            </a>
        </li>
        {% else %}
        <li class="page0item disabled">
            <a class="page-link" tabindex="-1" aria-disabled="true" href="#">
                다음
            </a>
        </li>
        {% endif %}
    </ul>
<!--    페이징 끝-->
    <a href="{% url 'pybo:question_create' %}" class="btn btn-primary">
            질문 등록
        </a>
</div>
{% endblock %}

추가한게 굉장히 많다.

 

question_list가  views.py에서 전달된 페이지된 결과 객체이다.

 

즉, question_list.previous_page_number 는 페이지화되어 입력받은 페이지에서 이전 페이지와 같은 의미이다.

 

쉽게 풀어 설명하자면, question_list가 이전에 300여개의 리스트였다면,

views.py에서 paginator를 통해서 10개 묶음으로 자른 다음, pybo에서  GET으로 page인자를 전달받고, 

page 숫자에 해당하는 묶음을 html로 전달한다. 

paginator는 previous_page_number 처럼 이전 페이지를 반환할 수 있다. 

 

즉 이전 페이지가 있다면, 이전 링크와 처음 링크를 활성화 시키고 이동할 수 있게 한다.

 

다음 버튼과 마지막 버튼도 마찬가지이다.

 

이제 한번에 보여지는 페이지 개수를 줄이는 단계이다.

 

{% for page_number in question_list.paginator.page_range %}
    {% if page_number >= question_list.number|add:-5 and page_number <= question_list.number|add:5 %}
        {% if page_number == question_list.number %}
        <li class="page-item active" aria-current="page">
            <a class="page-link" href="?page={{ page_number }}">
                {{ page_number }}
            </a>
        </li>
        {% else %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_number }}">
                {{ page_number }}
            </a>
        </li>
        {% endif %}
    {% endif %}
{% endfor %}

 

이 구문을 보면,

paginator.page_range 를 for문을 통해서 반복하는데, 

 

여기서 할당되는 page_number가 question_list.number ( = 현재 페이지 번호 ) 보다 5작거나 같은 경우,

 

그리고 5보다 큰 범위 일때만 출력하게한다.

|add:-5는 -5만큼 더하라, 즉 5만큼 빼라는 의미이고, 동일하게 |add:5는 5만큼 더하라는 의미이다.

 

자 이제 페이징기능이 끝났다.

반응형